Accesso al tipo di puntatore a funzione delle classi base del modello
-
21-08-2019 - |
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.
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;
};