2012-08-30 31 views
57

Ho iniziato a provare lo standard C++ 11 e ho trovato la domanda this che descrive come chiamare il tuo ctor da un altro operatore nella stessa classe per evitare di avere un metodo init o simili. Ora sto cercando la stessa cosa con il codice che assomiglia a questo:Inizializzazione membro durante l'utilizzo del costruttore delegato

HPP:

class Tokenizer 
{ 
public: 
    Tokenizer(); 
    Tokenizer(std::stringstream *lines); 
    virtual ~Tokenizer() {}; 
private: 
    std::stringstream *lines; 
}; 

cpp:

Tokenizer::Tokenizer() 
    : expected('=') 
{ 
} 

Tokenizer::Tokenizer(std::stringstream *lines) 
    : Tokenizer(), 
    lines(lines) 
{ 
} 

Ma questo mi sta dando l'errore: In constructor ‘config::Tokenizer::Tokenizer(std::stringstream*)’: /path/Tokenizer.cpp:14:20: error: mem-initializer for ‘config::Tokenizer::lines’ follows constructor delegation ho ho provato a spostare la parte Tokenizer() prima e ultima nell'elenco, ma ciò non ha aiutato.

Qual è la ragione di questo e come dovrei risolverlo? Ho provato a spostare il lines(lines) sul corpo con this->lines = lines; invece e funziona bene. Ma mi piacerebbe davvero essere in grado di utilizzare l'elenco di inizializzazione.

Grazie in anticipo!

risposta

76

Quando si delega l'inizializzazione membro all'altro costruttore, si presuppone che l'altro costruttore inizializza l'oggetto completamente, compresi tutti i membri (cioè compreso il lines membro nel tuo esempio). Non è quindi possibile inizializzare nuovamente alcun membro.

La citazione pertinente dal standard è (sottolineatura mia):

(§12.6.2/6) A mem-initializer-list can delegate to another constructor of the constructor’s class using any class-or-decltype that denotes the constructor’s class itself. If a mem-initializer-id designates the constructor’s class, it shall be the only mem-initializer; the constructor is a delegating constructor, and the constructor selected by the is the target constructor. [...]

È possibile lavorare-intorno a questo definendo la versione del costruttore che accetta argomenti primo:

Tokenizer::Tokenizer(std::stringstream *lines) 
    : lines(lines) 
{ 
} 

e quindi definire il costruttore predefinito utilizzando la delega:

Tokenizer::Tokenizer() 
    : Tokenizer(nullptr) 
{ 
} 

Come regola generale, è necessario specificare completamente la versione del costruttore che prende il maggior numero di argomenti e quindi delegare dalle altre versioni (utilizzando i valori predefiniti desiderati come argomenti nella delega).

+2

All'inizio sembra controintuitivo, ma in realtà aiuta davvero! – Korchkidu

Problemi correlati