2010-02-18 11 views
111

¿Es posible usar la lista de inicialización de un constructor de clase hijo para inicializar los miembros de datos declarados como protegidos en la clase padre? No puedo conseguir que funcione. Puedo evitarlo, pero estaría bien si no tuviera que hacerlo.Inicializar los miembros protegidos del padre con la lista de inicialización (C++)

un código de ejemplo:

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

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

Cuando intento esto, el compilador me dice: "clase 'niño' no tiene ningún campo denominado 'algo'". Es algo como esto posible? Si es así, ¿cuál es la sintaxis?

¡Muchas gracias!

Respuesta

103

No es posible en la forma que usted describe. Deberá agregar un constructor (podría estar protegido) a la clase base para reenviarlo. Algo así como:

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

    std::string something; 
} 

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

Esta es exactamente la solución que ya había llegado con. Al menos ahora no tengo que preocuparme si se puede o no hacer. :) – Stephen

11

Usted no puede inicializar los miembros de la clase padre en la lista de inicialización de constructor de clase derivada. No importa si están protegidos, públicos o cualquier otra cosa.

En el ejemplo, el miembro something es miembro del Parent clase, lo que significa que sólo se puede inicializar en la lista de inicialización del constructor de la clase Parent.

51

Cuando el compilador se encuentra con la lista de inicializadores, el objeto de clase derivado aún no se ha formado. El constructor de la clase base no ha sido llamado hasta entonces. Solo después de que se haya llamado al constructor de la clase base, se convierte en something. De ahí el problema. Cuando no llama explícitamente al constructor de la clase base, el compilador hace eso por usted (generando el constructor trivial apropiado para la clase base). Esto hace que el miembro something se inicialice por defecto.

De C++ 0x proyecto:

12.6.2 bases Inicialización y miembros

nombres en una mem-inicializador-id están miraron en el alcance de la clase del constructor y, si no se encuentra en ese ámbito, se busca en el ámbito que contiene la definición del constructor . [Nota: si la clase la de constructor contiene un miembro de con el mismo nombre que un directa o clase base virtual de la clase, una mem-inicializador-id nombrar la clase de miembro o base y compuesto de una sola identificador refiere al miembro de la clase. Se puede especificar una identificación de meminitizador para la clase base oculta utilizando un nombre calificado . nota -fin] A menos que los nombres mem-inicializador-ID de clase del del constructor, un conjunto de datos no estáticos miembros de la clase del constructor o una base directa o virtual de esa clase, la mem-inicializador está mal formada, .

Nota: Énfasis mío.

+2

Gracias por señalarme el "por qué". Tiene sentido total He estado alejado de C++ durante demasiado tiempo ... :) – Stephen

0

Tal vez usted puede tratar de esa manera el uso de la palabra clave "usando"

class Parent 
{ 

protected: 
std::string something; 
}; 

class Child : public Parent 
{ 

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