Les destructeurs virtuels sont utiles lorsque vous pouvez potentiellement supprimer une instance d'une classe dérivée via un pointeur vers la classe de base:
class Base
{
// some virtual methods
};
class Derived : public Base
{
~Derived()
{
// Do some important cleanup
}
};
Ici, vous remarquerez que je n'ai pas déclaré le destructeur de Base virtual
. Voyons maintenant l'extrait de code suivant:
Base *b = new Derived();
// use b
delete b; // Here's the problem!
Depuis la base de destructor n'est pas virtual
et b
est un Base*
pointage à un Derived
objet, delete b
a un comportement non défini :
[En delete b
], si le type statique de l'objet à supprimer est différent de son type dynamique, le type statique doit être une classe de base du type dynamique de l'objet à supprimer et le type statique doit avoir un destructeur virtuel ou le le comportement n'est pas défini .
Dans la plupart des implémentations, l'appel au destructeur sera résolu comme tout code non virtuel, ce qui signifie que le destructeur de la classe de base sera appelé mais pas celui de la classe dérivée, ce qui entraînera une fuite de ressources.
Pour résumer, faites toujours les destructeurs des classes de base virtual
quand ils sont destinés à être manipulés de manière polymorphe.
Si vous souhaitez empêcher la suppression d'une instance via un pointeur de classe de base, vous pouvez rendre le destructeur de classe de base protégé et non virtuel; ce faisant, le compilateur ne vous permettra pas d'appeler delete
un pointeur de classe de base.
Vous pouvez en savoir plus sur la virtualité et le destructeur de classe de base virtuelle dans cet article de Herb Sutter .