2012-08-30 22 views
57

He comenzado a probar el estándar C++ 11 y encontré this pregunta que describe cómo llamar a su ctor desde otro ctor en la misma clase para evitar tener un método init o similar. Ahora estoy intentando lo mismo con el código que se parece a esto:Inicialización de miembro al usar el constructor delegado

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) 
{ 
} 

Pero esto me está dando el error: In constructor ‘config::Tokenizer::Tokenizer(std::stringstream*)’: /path/Tokenizer.cpp:14:20: error: mem-initializer for ‘config::Tokenizer::lines’ follows constructor delegation tengo intenté mover la parte Tokenizer() primero y último en la lista, pero eso no ayudó.

¿Cuál es la razón detrás de esto y cómo debo solucionarlo? Intenté mover el lines(lines) al cuerpo con this->lines = lines; y funciona bien. Pero me gustaría poder usar la lista de inicializadores.

¡Gracias de antemano!

Respuesta

76

Al delegar la inicialización miembro a otro constructor, hay una suposición de que el otro constructor inicializa el objeto por completo, incluyendo todos los miembros (es decir, incluyendo el miembro lines en su ejemplo). Por lo tanto, no puede inicializar a ninguno de los miembros nuevamente.

La cita relevante de la norma IS (el énfasis es mío):

(§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. [...]

se puede trabajar-en torno a esto definiendo la versión del constructor que toma argumentos primera:

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

y luego defina el constructor predeterminado usando la delegación:

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

Como regla general, debe especificar completamente la versión del constructor que toma la mayor cantidad de argumentos y luego delegar desde las otras versiones (usando los valores predeterminados deseados como argumentos en la delegación).

+2

Parece contradictorio al principio, pero realmente está ayudando en realidad! – Korchkidu

Cuestiones relacionadas