2009-10-28 9 views
11

tengo una clase llamada MyBase que tiene un constructor y el destructor:¿Se llama el constructor y el destructor de una clase base con los derivados?

class MyBase 
{ 
public: 
    MyBase(void); 
    ~MyBase(void); 
}; 

y tengo una clase llamada plátano, que se extiende MyBase así:

class Banana:public MyBase 
{ 
public: 
    Banana(void); 
    ~Banana(void); 
}; 

¿La implementación del nuevo constructor y destructor en Banana anulan los de MyBase, o aún existen, y se les llama say antes o después de que se ejecute el constructor/destructor de Banana?

Gracias, y mis disculpas si mi pregunta parece tonta.

+9

Los dos mejores maneras de obtener respuestas a preguntas sencillas C++: 1) escribir un caso de prueba sencilla (por ejemplo, poner COUTS en los constructores y destructores), y 2) ver si es contestada en http: // www. parashift.com/c++-faq-lite/ – Artelius

+0

Por lo general, es útil que la pregunta sea relevante para lo que se está preguntando, en lugar de hacer que todos miren la descripción para ver lo que en realidad se está preguntando. –

+0

Este código no se compila por una serie de razones. Es decir. una clase Banana no puede tener un destructor "~ MyBase()". Verifica tu código antes de publicar. –

Respuesta

6

Debe decir

class Banana : public MyBase 
{ 
public: 
    Banana(void); 
    ~Banana(void); 
}; 

El constructor de la clase derivada se llama después del constructor de la clase base. Los destructores son llamados en orden inverso.

2

Le falta el tipo de herencia:

Cambio

class Banana:MyBase 

Para:

class Banana: public MyBase 

En cuanto a

hace la aplicación de la nueva constructor y re Estructor en Banana anulan los de MyBase, o ¿ aún existen, y se llaman antes del o después de que se ejecuta el constructor Banana/ destructor?

El orden de los heredados se ejecuta de abajo hacia arriba, lo que significa que primero se llamará MyBase y luego a Banana. Si tuviera otra subclase, se llamaría la última.

Tome este ejemplo:

class RottenBanana : public Banana 

La cadena de herencia es ahora RottenBanana -> Banana -> MyBase

Los constructores de esta clase se llamará a partir de las MyBase, a continuación, plátano y luego llamar RottenBanana.

+2

El tipo de herencia es opcional, cuando no lo indica, será una herencia 'privada' para las clases y 'pública' para las estructuras (el mismo nivel de acceso predeterminado que para todos los miembros). Además, la respuesta es un poco impreciso con la cadena de llamada del constructor: la lista de inicialización del objeto más derivado es lo primero que comienza a ejecutarse, que encadena con una llamada implícita o explícita a su constructor base, la lista de inicialización de ese constructor se iniciará y así sucesivamente ... el primer constructor para completar será el constructor de MyBase como usted declara, luego abajo de la jerarquía –

14

Un constructor de base siempre se llamará antes que el constructor derivado. Se llamará al destructor Base después de Dervided destructor.

Puede especificar en el constructor derivado qué constructor Base desea, si no se ejecutará el predeterminado.

Si define otros constructores pero no es el predeterminado y no especifica en el constructor Derivado cuál ejecutar, intentará el predeterminado que no existe y se bloqueará la compilación.

Lo anterior ocurre porque una vez que declaras un constructor no se generan constructores por defecto.

7

Los constructores no pueden ser anulados. No puede declarar un constructor de clase base en una clase derivada. Un constructor de clase tiene que llamar al un constructor en la clase base (si no se especifica uno, se llama al constructor predeterminado) antes que cualquier otra cosa.

Para poder limpiar la clase derivada correctamente, debe declarar el destructor de la clase base como virtual:

virtual ~MyBase() { ... } 
+3

El destructor no será anulado. La palabra clave virtual realiza una entrada en la tabla de métodos virtuales para que se llame primero al destructor más derivado incluso cuando se elimina mediante un puntero a una clase base. Pero se invocarán todos los destructores de las bases después de que se complete el destructor más derivado. Es decir, no anula, solo garantiza que el destructor más derivado recibe llamadas en todas las situaciones. –

+0

@dribeas: cierto. Editado para evitar confusiones. Por supuesto, está anulando técnicamente un método virtual. Sin embargo, al igual que la llamada al constructor de la clase base que es necesaria y el compilador la inserta automáticamente si no se especifica explícitamente, la llamada al destructor base se insertará en el destructor anulado; llamando efectivamente al destructor base después de que la implementación derivada haya finalizado. –

3

Los constructores se llaman de arriba hacia abajo en el árbol de herencia. Esto es para que el constructor derivado pueda contar con que el objeto base se inicialice completamente antes de intentar usar cualquier propiedad de la base.

Destructores se llaman en orden inverso de los constructores, por la misma razón: las clases derivadas dependen de la base, pero la base no depende de la derivada.

Si hay cualquier posibilidad de destruir el objeto a través de un puntero a una clase base, debe declarar todos los destructores virtual.

4

Los constructores y los destructores son funciones especiales de los miembros. En general, leerá en todas partes que la construcción comienza desde el tipo menos derivado en todo el camino en la jerarquía hasta el tipo más derivado. Este es realmente el orden en que se completa la ejecución del constructor, pero no cómo se inicia la construcción.

constructores lista de inicialización orden de ejecución garantiza que, si bien el constructor del objeto más derivada será el primer constructor para comenzar a ejecutar será el último constructor para completar

Cuando se instancia un objeto al constructor más derivada que coincide la llamada de construcción se llama primero. La lista de inicialización del constructor derivado más emparentado comienza, y las listas de inicialización tienen un orden fijo: primero se llama a los constructores de las clases base en orden o apariencia dentro de la lista de herencia. A continuación, los constructores de atributo miembro se invocan en el orden en que aparecen en la declaración de clase (no en el orden en que aparecen en la lista de inicialización). Una vez completada la lista de inicialización completa (en cada nivel), se ejecuta el bloque del cuerpo del constructor, después de lo cual se completa la llamada del constructor.

Todos los destructores de base serán llamados en el orden inverso de construcción después de que el destructor más derivado haya completado la ejecución. La destrucción ocurre en el orden inverso exacto de construcción.

Los destructores son especiales de una manera diferente: no pueden ser anulados. Cuando llame al destructor más derivado de una clase, completará la ejecución del cuerpo destructor, después de lo cual se llamarán todos los destructores de atributo miembro en orden inverso de creación. Después de que el destructor más derivado se haya completado y lo hayan hecho los miembros destructores del objeto más derivado, el destructor de sus bases más directas comenzará en el orden inverso de construcción, los cuerpos del destructor se ejecutarán, luego el miembro asignará destructores y así sucesivamente. . Al final todos los elementos construidos serán destruidos.

destructores de las clases polimórficas deben ser virtual

La descripción anterior destrucción comienza con la llamada al destructor más derivada.Esto se puede lograr llamando al delete en un puntero al tipo más derivado, cuando un objeto automático sale del alcance o cuando el objeto es delete d a través de una clase base cuyo destructor es virtual.

Si olvida agregar la palabra clave destructor en la clase base e intenta eliminar un objeto derivado mediante un puntero a la base, llamará al destructor base directamente, y eso implica que todos los sub objetos debajo del puntero teclearán la jerarquía no será destruida apropiadamente. Todas las jerarquías de herencia en las que eliminará objetos mediante punteros a un tipo base deben tener destructores virtuales. Como regla general, si ya tiene un método virtual, el costo de hacer que el destructor sea virtual es insignificante y es una red segura. Muchas guías de codificación hacen cumplir que los destructores en las jerarquías de herencia deben ser virtuales. Algunos llegan incluso a pedir que todos los destructores sean virtuales. Esto tiene la intención de evitar posibles fugas de recursos a costa de agregar un vtable para todos los tipos y un puntero vtable para todos los objetos.

-2

Si crea una instancia de un objeto EEGModeRGB (que tiene un LED tricolor), elimínelo inmediatamente y verá los colores Azul, Verde, Amarillo y Rojo, durante un segundo cada uno, en ese orden.

class EEGMode { 
public: 

    EEGMode() { setAllPixelsToColor(BLUE); delay(1000); } 
    virtual ~EEGMode() { setAllPixelsToColor(RED); delay(1000); } 

}; 


class EEGModeRGB : public EEGMode { 
public: 

    EEGModeRGB() { setAllPixelsToColor(GREEN); delay(1000); } 
    virtual ~EEGModeRGB() { setAllPixelsToColor(YELLOW); delay(1000); } 

}; 
Cuestiones relacionadas