Virtual Destructor in C++

Virtual Destructor In C



C ++ es el lenguaje que se utiliza para dar una base en el concepto básico de programación y fortalece el pensamiento lógico de los programadores. En C ++, OOP juega un papel vital ya que OOP es un lenguaje orientado a objetos que crea los objetos de las clases. En OOP, estudiamos las clases y los objetos. Las clases contienen los miembros de datos que son variables de diferentes tipos y diferentes funciones miembro. Con la ayuda de instancias, accedemos a los datos de cualquier clase. Cada clase tiene su constructor y destructor cuando creas la clase. El constructor se llama a sí mismo cuando se crea el objeto de esa clase. También podemos inicializar las variables de una clase dentro del constructor. Los destructores también se crean automáticamente con el constructor, pero los destructores destruyen el objeto y es la última función que se llama antes de destruir el objeto. Se crea el nombre de la clase, por ejemplo, la clase 'Profesión'. Su constructor es Profession() y el destructor es ~Profession(). Los tres tienen el mismo nombre.

Después de hablar sobre la POO, los constructores y los destructores, hablemos ahora de los destructores virtuales. Los destructores virtuales, como su nombre lo especifica, destruyen el objeto. Tenemos una clase base y una clase derivada que se deriva de la clase base. Ambas clases tienen sus constructores y destructores. El destructor virtual libera la memoria que se asigna a través del objeto de la clase derivada mientras elimina los objetos de la clase derivada utilizando un puntero de clase base con la palabra clave 'virtual'.

¿Por qué usamos el Destructor Virtual?

Cuando la ejecución de las funciones de los miembros de la clase finaliza o la ejecución del método main() está a punto de finalizar, se llama automáticamente al destructor para liberar la memoria asignada durante la creación del objeto. Ahora, ¿por qué usamos un destructor virtual? Cuando se elimina la clase base que apunta a la clase derivada, aquí se usa el puntero (*). El destructor de clase base solo se llama durante este proceso. El destructor de clase derivado no se llama, lo que genera problemas. Uno de ellos es un problema de pérdida de memoria. Para evitar este problema y hacer que nuestro código sea seguro, destruimos virtualmente los objetos para liberar el espacio de memoria que se asignó durante la creación de objetos al eliminar el destructor de clase base.

Ejemplo básico de C++ sin Virtual Destructor

Veamos cómo funciona el programa sin un destructor virtual con un programa simple que elimina el puntero.

Código:

#incluir

usando el espacio de nombres estándar ;
clase Padre_Clase0
{
público :
Padre_Clase0 ( )
        { cout << 'Constructor de clase principal' << final ; }
~Parent_Class0 ( )
        { cout << 'Destructor de clase principal' << final ; }
} ;
clase Niño_1 : public Parent_Class0
{
público :
Niño_1 ( )
        { cout << 'Constructor de clase infantil' << final ; }
~Niño_1 ( )
        { cout << 'Destructor de clase infantil' << final ; }
} ;
En t principal ( )
{
Padre_Clase0 * puntero = nuevo Niño_1 ( ) ;
Eliminar puntero ;
    devolver 0 ;
}

Este código explica cómo se ejecuta el código sin un destructor virtual. En primer lugar, cree una clase llamada 'Parent_Class0' que será la clase principal. Dentro de esta clase, crea un constructor y un destructor. Como sabemos, el constructor y el destructor se nombran igual que la clase. El destructor se representa de manera similar al constructor pero tiene un símbolo (~) que lo diferencia del constructor. Dentro del constructor y destructor, imprime un mensaje usando “cout<<”. Ahora, cree otra clase que sea 'Child_1'. Esta clase se deriva de la clase principal, 'Parent_Class0'. La clase derivada tiene su constructor y destructor que contienen un mensaje para imprimir en la pantalla de salida.

En el método main(), creamos una instancia de “Parent_Class0” y le asignamos una clase derivada. El punto crucial a recordar en este caso es que utilizamos un puntero para recuperar la clase principal. Cuando entra en la clase principal, ejecuta el constructor de la clase principal. Luego, va a la clase secundaria y ejecuta su constructor. Antes de ejecutar el destructor de la clase secundaria, debe ejecutar el destructor de la clase principal. El compilador ejecuta el destructor de la clase principal y finaliza la clase sin ejecutar el destructor de una clase secundaria. Ese es el problema; no libera la memoria de la clase del niño. Representa el constructor de una clase principal, el constructor de una clase secundaria y el destructor de una clase principal. Eso muestra que el destructor de una clase secundaria no se ejecuta. Después de esta ejecución, borramos el puntero en la función main().

Producción:

Ejemplo de C++ con Destructor Virtual

Analicemos el destructor virtual con un código simple para diferenciar cómo funciona con y sin un destructor virtual.

Código:

#incluir

usando el espacio de nombres estándar ;
clase Padre_Clase0
{
público :
Padre_Clase0 ( )
        { cout << 'Constructor de clase principal' << final ; }
~Parent_Class0 virtual ( )
        { cout << 'Destructor de clase principal' << final ; }
} ;
clase Niño_1 : public Parent_Class0
{
público :
Niño_1 ( )
        { cout << 'Constructor de clase infantil' << final ; }
~Niño_1 virtual ( )
        { cout << 'Destructor de clase infantil' << final ; }
} ;
En t principal ( )
{
Padre_Clase0 * puntero = nuevo Niño_1 ( ) ;
Eliminar puntero ;
    devolver 0 ;
}

El primer programa explicaba el problema al que nos enfrentamos sin un destructor virtual. Ahora, este código resolverá ese problema usando un destructor virtual. Primero, copie el primer código y simplemente agregue una palabra clave en dos lugares de este programa. Esa palabra es 'virtual'. Inserte esta palabra con el destructor de la clase padre, “Parent_Class0”. Del mismo modo, mencione esto con el destructor de la clase secundaria que es 'Child_1' que se deriva de la clase principal. Esta palabra clave 'virtual' hace un pequeño cambio y ejecuta primero el destructor de la clase secundaria 'Child_1'. Luego, ejecuta el destructor de la clase padre, “Parent_Class0”. El resto del programa funciona igual que sin un destructor virtual. Al agregar este pequeño fragmento de código, podemos salvar nuestra memoria de fugas. Ahora, muestra cuatro mensajes en la consola. Primero, el constructor de una clase principal, luego el constructor de una clase secundaria, el destructor de una clase secundaria y el destructor de una clase principal. Al final, eliminamos el puntero dentro del método main().

Producción:

Ejemplo en C++ de destructor virtual puro

En este código, hablaremos sobre el destructor virtual puro, cómo funciona y en qué se diferencia de un destructor virtual.

Código:

#incluir

clase padre_0 {
público :
~Parent_0 virtual ( ) = 0 ;
} ;
Padre_0 :: ~Padre_0 ( )
{
estándar :: cout << 'Hola, soy Pure Destructor. ¡Me llamaste!' ;
}
clase Niño_0 : padre público_0 {
público :
~Niño_0 ( ) { estándar :: cout << 'El destructor derivado está aquí \norte ' ; }
} ;

En t principal ( )
{
Padre_0 * ptr_0 = nuevo Niño_0 ( ) ;
eliminar ptr_0 ;
    devolver 0 ;
}

La clase principal 'Parent_0' se crea en el primer paso del código. Dentro de él, cree el destructor principal virtual y asígnele 0. Esto establece el destructor virtual en un destructor virtual puro, lo que significa que la clase principal ahora es abstracta y no podemos crear las instancias de esta clase. Fuera de la clase principal 'Parent_0', defina los destructores y std::cout. El texto requerido se muestra utilizando std::cout. Luego, derive una clase 'Child_0' de la clase principal y defina su destructor. Dentro del destructor, imprime un mensaje. En la función main(), cree el puntero de la clase principal y asígnele la clase secundaria.

El compilador va a la clase principal 'Parent_0'. Cuando se crea el puntero, se llama automáticamente a su constructor. Luego, el compilador ingresa a la clase secundaria para invocar a su constructor. Después de la ejecución exitosa del constructor, ejecuta el destructor de una clase secundaria 'Child_0'. Luego, ejecuta el destructor de una clase padre. De esta manera, podemos hacer un destructor virtual puro. No se recomienda utilizarlo porque al emplear este método, la clase principal se vuelve abstracta, lo que la hace inútil. La metodología que mayormente se utiliza es virtual destructor y es una buena práctica.

Producción:

Conclusión

Aprendimos sobre el destructor virtual a partir del concepto de programación orientada a objetos para avanzar hacia los constructores y destructores. Después de explicar todo esto, hablamos sobre el destructor virtual en detalle con ejemplos de codificación y destructor virtual puro. Antes de explicar el destructor virtual, debemos conocer los constructores, los destructores y la herencia. En herencia, heredamos las clases de una clase padre. Las clases secundarias pueden ser más de una, pero la clase principal es solo una. Los destructores virtuales y los destructores virtuales puros se aplican en herencia para evitar la fuga de memoria. Desde el ejemplo básico hasta el ejemplo avanzado, cubrimos todo lo que debe saber para comenzar a usar y destruir virtualmente la memoria de la clase derivada.