Domanda

Ho un corso che mi è stato fornito che non voglio davvero cambiare, ma voglio estenderlo.Sono un principiante di pattern e template e sto sperimentando un pattern Decorator applicato a una classe di template.La classe modello contiene un puntatore a membro (se capisco correttamente la semantica) in un'altra classe ancora.Il puntatore a membro è il deserializzatore di un istream XML.Il tipo 'T' è il tipo di documento XML da deserializzare.

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;

};

Il typedef mi sembra strano dopo averlo letto http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.5, eppure questa classe sembra funzionare bene così com'è.Non ci sono #define aggiuntive nel file di intestazione fornito, quindi questo è un po' misterioso per me.

Ora provo ad estenderlo, come Decoratore perché voglio lavorare un po' di più sull'oggetto auto_ptr restituito da 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)
{ }

Quando provo a compilarlo, ricevo un reclamo sulla sintassi nelle due righe mostrate.L'errore è qualcosa come "previsto ')' in *".Non c'è alcuna lamentela sul fatto che MYFUN sia indefinito.

Quando ridefinisco il puntatore a membro in D con la stessa firma di D, cioè

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

Funziona.Preferisco non doverlo fare per ogni D/Decorator che potrei fare di B.Ho provato a eseguire typedef in modo più globale, ma non sono riuscito a ottenere la sintassi corretta perché il parametro del modello non era definito.

È stato utile?

Soluzione

L'errore di compilazione è dovuto al fatto che il compilatore non può dire che si sta parlando di un tipo.

Prova:

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

e

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

Si veda: sezione Modelli del C ++ FAQ Lite per maggiori dettagli su questo il motivo per cui è necessario, ma la sintesi è che, a causa della possibilità di modello di specializzazione, non v'è alcun modo per il compilatore per essere sicuri che B<T>::MYFUN è in realtà riferimento a un tipo.

Altri suggerimenti

La definizione del typedef MYFUN in B è fatto con la visibilità privata. D non sarà in grado di accedervi. Se si cambia in protetto o pubblico, lo fa poi il lavoro?

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

Il problema che vedo con questo è che B::MYFUN è a privato typedef.

Pertanto, qualsiasi classe ereditaria non può accedervi.

Cambialo in:

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;
};
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top