Destruidores virtuais são úteis quando você pode excluir potencialmente uma instância de uma classe derivada através de um ponteiro para a classe base:
class Base
{
// some virtual methods
};
class Derived : public Base
{
~Derived()
{
// Do some important cleanup
}
};
Aqui, você notará que eu não declarei ser o destruidor da Base virtual
. Agora, vamos dar uma olhada no seguinte trecho:
Base *b = new Derived();
// use b
delete b; // Here's the problem!
Como o destruidor do Base não é virtual
e b
é um Base*
apontador para um Derived
objeto, delete b
tem um comportamento indefinido :
[In delete b
], se o tipo estático do objeto a ser excluído for diferente do seu tipo dinâmico, o tipo estático deve ser uma classe base do tipo dinâmico do objeto a ser excluído e o tipo estático deve ter um destruidor virtual ou o comportamento é indefinido .
Na maioria das implementações, a chamada ao destruidor será resolvida como qualquer código não virtual, o que significa que o destruidor da classe base será chamado, mas não o da classe derivada, resultando em um vazamento de recursos.
Para resumir, sempre faça destruidores das classes base virtual
quando elas forem manipuladas polimorficamente.
Se você deseja impedir a exclusão de uma instância por meio de um ponteiro de classe base, você pode tornar o destruidor da classe base protegido e não virtual; ao fazer isso, o compilador não permitirá que você chame delete
um ponteiro de classe base.
Você pode aprender mais sobre virtualidade e destruidor de classe base virtual neste artigo em Herb Sutter .