¿Por qué se llama al constructor predeterminado en la herencia virtual?

2 minutos de lectura

¿Por que se llama al constructor predeterminado en la herencia
Simón Desfarges

No entiendo por qué en el siguiente código, cuando instancia un objeto de tipo daughterel valor por defecto grandmother() se llama el constructor?

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

Aquí el compilador llama silenciosamente grandmother constructor predeterminado 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);
}

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

    – orlp

    28 de marzo de 2012 a las 12:46


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

    – Simón Desfarges

    28 de marzo de 2012 a las 12:47


  • g ++ 4.1.2 tiene el mismo problema: codepad.org/L0jBXfSP

    – orlp

    28 de marzo de 2012 a las 12:49

  • La instantánea de Ubuntu 4.7 con -Wall -pedantic-errors reproduce esto.

    – juanchopanza

    28 de marzo de 2012 a las 12:51

1646758030 302 ¿Por que se llama al constructor predeterminado en la herencia
interjay

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

Como no llamaste explícitamente grandmother constructor en la lista de inicialización, se llamará al constructor predeterminado. Para llamar al constructor correcto, cámbielo a:

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

Ver también Esta entrada de preguntas frecuentes.

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

    – Aurélien Ribón

    28 de marzo de 2012 a las 13:03


  • Gracias ! Entonces, en caso de herencia virtual, lo mejor que se puede hacer es llamar manualmente a todos los constructores de la cadena.

    – Simón Desfarges

    28 de marzo de 2012 a las 13:11

  • @Xriuk Se refiere a constructores de clases que se heredaron mediante herencia virtual.

    – interjay

    08/01/2016 a las 15:34

  • ¿Eso significa que la abuela será llamada dos veces? ¿Qué pasa con la llamada a la abuela dentro de la madre?

    – Youda008

    9 de abril de 2016 a las 14:14

  • @ Youda008 Se llamará una vez. la llamada de mother será ignorado, a menos que cree una instancia directamente mother en lugar de una clase derivada.

    – interjay

    09/04/2016 a las 16:32

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad