c++ - tipos - Inicialización de miembros al usar un constructor delegado
qué es un constructor en c++? (1)
Empecé probando el estándar C ++ 11 y encontré this pregunta que describe cómo llamar a tu ctor desde otro ctor en la misma clase para evitar tener un método init o similar. Ahora estoy intentando lo mismo con un código que se ve así:
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
He intentado mover la parte de Tokenizer () primero y último en la lista, pero eso no ayudó.
¿Cuál es la razón detrás de esto y cómo debería solucionarlo? Intenté mover las lines(lines)
al cuerpo con this->lines = lines;
en su lugar y funciona bien. Pero me gustaría poder usar la lista de inicializadores.
¡Gracias por adelantado!
Cuando delega la inicialización de miembro a otro constructor, se supone que el otro constructor inicializa el objeto por completo , incluidos todos los miembros (es decir, incluido el miembro de lines
en su ejemplo). Por lo tanto, no puede inicializar a ninguno de los miembros nuevamente.
La cita relevante del Estándar es (énfasis mío):
(§12.6.2 / 6) Un mem-initializer-list puede delegar en otro constructor de la clase del constructor usando cualquier class-or-decltype que denote la propia clase del constructor. Si un mem-initializer-id designa la clase del constructor, será el único mem-initializer ; el constructor es un constructor delegante, y el constructor seleccionado por el es el constructor de destino. [...]
Puede solucionar esto definiendo la versión del constructor que toma argumentos primero :
Tokenizer::Tokenizer(std::stringstream *lines)
: lines(lines)
{
}
y luego define el constructor por defecto 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 (utilizando los valores predeterminados deseados como argumentos en la delegación).