Tengo una sólida comprensión de la mayor parte de la teoría OO, pero lo que me confunde mucho son los destructores virtuales.
Pensaba que el destructor siempre es llamado sin importar qué y para cada objeto en la cadena.
¿Cuándo hay que hacerlos virtuales y por qué?
Los destructores virtuales son útiles cuando se puede eliminar potencialmente una instancia de una clase derivada a través de un puntero a la clase base:
class Base
{
// some virtual methods
};
class Derived : public Base
{
~Derived()
{
// Do some important cleanup
}
};
Aquí, notarás que no declaré el destructor de Base como virtual
. Ahora, echemos un vistazo al siguiente fragmento:
Base *b = new Derived();
// use b
delete b; // Here's the problem!
Como el destructor de Base no es virtual
y b
es una Base*
que apunta a un objeto Derivado
, delete b
tiene comportamiento indefinido:
[En
delete b
], si el tipo estático del objeto a ser borrado es diferente de su tipo dinámico, el tipo estático tipo estático será una clase base del tipo dinámico del objeto a ser borrar y __el tipo estático debe tener un destructor virtual o el comportamiento comportamiento es indefinido.
En la mayoría de las implementaciones, la llamada al destructor se resolverá como cualquier código no virtual, lo que significa que se llamará al destructor de la clase base pero no al de la clase derivada, dando lugar a una fuga de recursos.
En resumen, haz siempre que los destructores de las clases base sean virtuales
cuando estén destinados a ser manipulados polimórficamente.
Si quieres evitar el borrado de una instancia a través de un puntero de la clase base, puedes hacer que el destructor de la clase base sea protegido y no virtual; al hacer esto, el compilador no te dejará llamar a delete
en un puntero de la clase base.
Puedes aprender más sobre la virtualidad y el destructor de clase base virtual en este artículo de Herb Sutter.
Declarar virtuales los destructores en las clases base polimórficas. Este es el punto 7 en Effective C++ de Scott Meyers. Meyers continúa resumiendo que si una clase tiene cualquier función virtual, debería tener un destructor virtual, y que las clases no diseñadas para ser clases base o no diseñadas para ser usadas polimórficamente no deberían declarar destructores virtuales.