J'ai une solide compréhension de la plupart des théories OO, mais la chose qui me trouble le plus est le destructeur virtuel.
Je pensais que le destructeur était toujours appelé, quoi qu'il arrive et pour chaque objet de la chaîne.
Quand doit-on les rendre virtuels et pourquoi ?
Les destructeurs virtuels sont utiles lorsque vous pouvez potentiellement supprimer une instance d'une classe dérivée par le biais d'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 comme étant virtuel
. Maintenant, regardons l'extrait suivant :
Base *b = new Derived();
// use b
delete b; // Here's the problem!
Puisque le destructeur de Base'n'est pas virtual
et que b
est une Base*
pointant vers un objet Derived
, delete b
a undefined behaviour :
[Dans
delete b
], si le type statique de l'objet à supprimer est objet à supprimer est différent de son type dynamique, le type statique doit être un type de base. statique doit être une classe de base du type dynamique de l'objet à supprimer et supprimé et __le type statique doit avoir un destructeur virtuel ou le comportement de l'objet est indéfini. Le comportement de l'objet est indéfini.
Dans la plupart des implémentations, l'appel au destructeur sera résolu comme n'importe quel 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, entraînant une fuite de ressources.
En résumé, il faut toujours rendre les destructeurs des classes de base virtuels
lorsqu’ils sont destinés à être manipulés de manière polymorphe.
Si vous voulez empêcher la suppression d'une instance par le biais d'un pointeur de classe de base, vous pouvez faire en sorte que le destructeur de la classe de base soit protégé et non virtuel ; en faisant cela, le compilateur ne vous laissera pas appeler delete
sur un pointeur de classe de base.
Vous pouvez en savoir plus sur la virtualité et le destructeur virtuel de classe de base dans [cet article de Herb Sutter][2].
Déclarer les destructeurs virtuels dans les classes de base polymorphes. Il s'agit du point 7 de l'article de Scott Meyers [Effective C++][1]. Meyers poursuit en résumant que si une classe possède n'importe quelle fonction virtuelle, elle doit avoir un destructeur virtuel, et que les classes qui ne sont pas conçues pour être des classes de base ou qui ne sont pas conçues pour être utilisées de manière polymorphe ne doivent pas déclarer de destructeurs virtuels.
[1] : http://www.amazon.com/Effective-Specific-Addison-Wesley-Professional-Computing/dp/0201924889