Pergunta

Eu tenho uma classe que eu tenho desde que eu realmente não quero mudar, mas eu quero estender. Eu sou um padrão e modelo novato experimentar com um padrão Decorator aplicada a uma classe de modelo. classe de modelo contém um ponteiro-para-membro (se eu entendi a semântica corretamente) em outra classe. O ponteiro-para-membro é o desserializador de um istream XML. O tipo 'T' é o tipo de documento XML para ser desserializado.

template <typename T> class B {
public:
  typedef std::auto_ptr<T> MYFUN( 
    std::istream&, const std::string&, const std::string& );

public:
  B<T>( MYFUN* p );

private:
  MYFUN *fptr;
  std::string aString1;
  std::string aString2;

};

Os typedef olhares estranhos para mim depois de ler http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.5 , e ainda assim esta classe parece funcionar bem como está. Não existem #defines adicionais no cabeçalho do arquivo fornecido, por isso este é um pouco misterioso para mim.

Agora eu tentar estendê-lo, como decorador, porque eu quero fazer um pouco mais de trabalho no objeto auto_ptr retornado por MyFun:

template <typename T>
class D : public class B<T>
{
  D( B<T>::MYFUN *fPtr, B<T> *providedBase ); //compiler complaint
  //Looks like B
  private:
    B* base_;

};

template <typename T>
D<T>::D( B<T>::MYFUN *p, B<T> *base ) //compiler complaint
:
B<T>::B( p ), base_(providedBase)
{ }

Ao tentar compilar isso, eu recebo uma queixa sintaxe nas duas linhas mostradas. Erro é algo como "esperado ')' em *". Não há nenhuma queixa sobre MyFun sendo indefinido.

Quando I re-definir o ponteiro-se membro em D com a mesma assinatura como em D, i.

//change MYFUN to NEWFUN in D)
typedef std::auto_ptr<T> MYNEWFUN( 
    std::istream&, const std::string&, const std::string& );

Isso funciona. Eu prefiro não ter que fazer isso para cada D / decorador eu poderia fazer de B. Tentei executar a typedef mais globalmente, mas não conseguiu obter o direito sintaxe devido ao parâmetro do modelo a ser indefinido.

Foi útil?

Solução

O erro de compilação é devido ao fato de que o compilador não pode dizer que você está falando de um tipo.

Tente:

D( typename B<T>::MYFUN *fPtr, B<T> *providedBase );

e

template <typename T>
D<T>::D( typename B<T>::MYFUN *p, B<T> *base )

Veja: a secção de modelos do C ++ FAQ Lite para obter mais detalhes sobre por que isso é necessário, mas o resumo é que, devido à possibilidade de especialização de modelo, não há nenhuma maneira para que o compilador para ter certeza de que B<T>::MYFUN está realmente se referindo a um tipo.

Outras dicas

A definição do typedef MyFun em B é feito com visibilidade privada. D não será capaz de acessá-lo. Se você alterá-lo para público protegido ou, não é então o trabalho?

template <typename T> class B {
  protected:
    typedef std::auto_ptr<T> MYFUN( 
      std::istream&, const std::string&, const std::string& );
...
};

O problema que vejo com isso é que B :: MyFun é a privada typedef.

Portanto, qualquer classe herdada não pode acessá-lo.

Alterar isso:

template <typename T> class B 
{  
public:
   typedef std::auto_ptr<T> MYFUN(     std::istream&, const std::string&, const std::string& );
public:  
   B<T>( MYFUN* p );
private:  
   MYFUN *fptr;  
std::string aString1;  
std::string aString2;
};
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top