2010-02-18 15 views
111

È possibile utilizzare l'elenco di inizializzazione di un costruttore di classi child per inizializzare i membri dati dichiarati come protetti nella classe genitore? Non riesco a farlo funzionare. Posso aggirarlo, ma sarebbe bello se non dovessi farlo.Inizializza i membri protetti del genitore con l'elenco di inizializzazione (C++)

Alcuni codice di esempio:

class Parent 
{ 
protected: 
    std::string something; 
}; 

class Child : public Parent 
{ 
private: 
    Child() : something("Hello, World!") 
    { 
    } 
}; 

Quando provo questo, il compilatore mi dice: "class 'Bambino' non ha alcun campo denominato 'qualcosa'". È possibile qualcosa del genere? In tal caso, qual è la sintassi?

Grazie mille!

risposta

103

Non è possibile nel modo in cui descrivi. Dovrai aggiungere un costruttore (potrebbe essere protetto) alla classe base per inoltrarlo. Qualcosa di simile:

class Parent 
{ 
protected: 
    Parent(const std::string& something) : something(something) 
    {} 

    std::string something; 
} 

class Child : public Parent 
{ 
private: 
    Child() : Parent("Hello, World!") 
    { 
    } 
} 
+2

Questo è esattamente la soluzione che avevo già venuta in mente. Almeno ora non devo preoccuparmi se possa essere fatto o meno. :) – Stephen

11

È Non possibile inizializzare i membri della classe padre nella lista di inizializzazione del costruttore della classe derivata. Non importa se sono protetti, pubblici o qualsiasi altra cosa.

Nell'esempio, l'elemento something è membro della classe Parent, il che significa che può essere inizializzato solo nell'elenco di inizializzatore costruttore della classe Parent.

51

Quando il compilatore trova l'elenco di inizializzazione, l'oggetto classe derivata deve ancora essere formato. Il costruttore della classe base non è stato chiamato fino ad allora. Solo dopo che il costruttore della classe base è stato chiamato, something diventa disponibile. Da qui il problema. Quando non si chiama esplicitamente il costruttore della classe base, il compilatore lo fa per te (generando il costruttore triviale appropriato per la classe base). Ciò causa l'inizializzazione del membro something.

Da C++ 0x progetto:

12.6.2 Inizializzazione basi e membri

nomi in un mem-inizializzatore-id sono alzò lo sguardo nel campo di applicazione della La classe di costruttore e, se non trovata, in questo ambito, viene cercata nell'ambito contenente la definizione del costruttore. [Nota: se la classe del costruttore contiene un membro con lo stesso nome di una diretta o virtuale classe base della classe, un mem-inizializzatore-id denominazione classe membro o base e composto da un unico identificatore riferisce al membro della classe. È possibile specificare un memoriz- zeride per la classe base nascosta utilizzando un nome qualificato . Nota -end] A meno che i nomi mem-inizializzatore-ID di classe della del costruttore, un dato non statici membri della classe del costruttore o un di base diretta o virtuale di quella classe, la mem-inizializzatore è mal formato .

Nota: enfasi.

+2

Grazie per avermi indicato al "perché". Ha un senso totale. Sono stato lontano da C++ per troppo tempo ... :) – Stephen

0

Forse si può provare in questo modo utilizzando la parola chiave "usando"

class Parent 
{ 

protected: 
std::string something; 
}; 

class Child : public Parent 
{ 

private: 
using Parent::something; 
Child() 
{ 
    something="Hello, World!"; 
} 
}; 
Problemi correlati