2012-03-28 27 views
62

No entiendo por qué en el siguiente código, cuando instancia un objeto de tipo daughter, se llama al constructor predeterminado grandmother()?¿Por qué se llama al constructor predeterminado en herencia virtual?

Pensé que se debería llamar al constructor grandmother(int) (para seguir las especificaciones de mi constructor de clase mother), o este código no debería compilarse en absoluto debido a la herencia virtual.

Aquí el compilador llama silenciosamente a grandmother constructor por defecto en mi espalda, mientras que nunca lo pedí.

#include <iostream> 

class grandmother { 
public: 
    grandmother() { 
     std::cout << "grandmother (default)" << std::endl; 
    } 
    grandmother(int attr) { 
     std::cout << "grandmother: " << attr << std::endl; 
    } 
}; 

class mother: virtual public grandmother { 
public: 
    mother(int attr) : grandmother(attr) { 
     std::cout << "mother: " << attr << std::endl; 
    } 
}; 

class daughter: virtual public mother { 
public: 
    daughter(int attr) : mother(attr) { 
     std::cout << "daughter: " << attr << std::endl; 
    } 
}; 

int main() { 
    daughter x(0); 
} 
+0

¿Qué compilador (y versión)? ¿Con qué argumentos lo compilaste? – orlp

+0

gcc 4.6.3 20120306 (Red Hat 4.6.3-2) en fedora 15. Los argumentos son: -O0 -g3 -Wall -c -fmessage-length = 0 –

+0

g ++ 4.1.2 tiene el mismo problema: http: // codepad.org/L0jBXfSP – orlp

Respuesta

66

Al utilizar herencia virtual, constructor de la clase base virtual se llama directamente por el constructor de la clase más derivada. En este caso, el constructor daughter llama directamente al constructor grandmother.

Como no ha llamado explícitamente al constructor grandmother en la lista de inicialización, se llamará al constructor predeterminado. Para llamar al constructor correcta, cambie a:

daugther(int attr) : grandmother(attr), mother(attr) { ... } 

Ver también This FAQ entry.

+2

Eso tiene mucho sentido, ¡gracias! Todos los constructores en la jerarquía son llamados desde la última clase y no por su clase secundaria respectiva. Nunca pensé en eso. Las especificaciones de C++ pueden ser difíciles a veces ... –

+0

¡Gracias! Entonces, en el caso de la herencia virtual, lo mejor es llamar manualmente a todos los constructores de la cadena. –

+0

¡Excelente respuesta! ¡Gracias! –

Cuestiones relacionadas