Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

destructeurs virtuels et héritage

14 réponses
Avatar
Edrusb
Bonjour,

j'ai une question toute bête :

Pour simplifier j'ai trois classes qui dérivent les unes des autres (A
-> B -> C) les objets de chaque classe peuvent être manipulés (alloués,
détruits) par des pointeurs des classes parents, j'ai donc besoin de
destructeur virtuels.

Est-ce que chaque classe doit définir un destructeur virtuel ou est-ce
que définir un destructeur virtuel pour la classe A implique que les
destructeurs implicites ou explicites des classes héritées sont virtuels
aussi:

Soit à dire est-ce que ces déclarations :

class A
{
public:
virtuel ~A() {};
};

class B : public A
{
public:
// pas de destructeur explicite
// ou destructeur explicite sans mot clef "virtuel"
};

class C : public B
public:
// pas de destructeur explicite
// ou destructeur explicite sans mot clef "virtuel"
};


suffisent pour utiliser le code suivant sans risque de fuite mémoire:

B *ptr1;
B *ptr2;

ptr1 = new B;
ptr2 = new C;

...

delete ptr1;
delete ptr2;

ou bien dois-je obligatoirement déclarer les classes B et C comme ceci:

class B : public A
{
public:
virtual ~B(){/* implémentation éventuelle */};
};

class C : public B
public:
virtual ~C(){/* implémentation éventuelle */};
};

Merci d'avance pour toute réponse.

--
Edrusb
edrusba@free.fr (supprimer le 'a')

4 réponses

1 2
Avatar
Sylvain
hibakusha wrote on 25/07/2007 18:34:
... ...
Il est nécessaire que toute classe dont une autre va dériver possède
un destructeur virtuel. ... ... ...


Nécessaire ? je pensais que le destructeur ne devait être virtuel que
lorsque l'on jouait ensuite avec le polymorphisme ?


déclaration (de variables) polymorphes ou appels polymorphes ?
dans le premier cas, un destructeur virtuel est nécessaire, sinon...

B* toto = new B();
delete toto;
... ...


mais

A* toto = new B();
delete toto;

ne marchera pas.

Ce sont bien les destructeurs de B puis de A qui seront executés ? pas
de polymorphisme ici donc pas besoin de destructeurs virtuels ?


certes mais définit-on un bon usage sur un seul exemple bati exprès pour?

Sylvain.


Avatar
hibakusha
En réponse à Fabien et Sylvain : je suis entierement d'accord avec vous.
Je comprends et j'approuve que l'on qualifie systématiquement un
destructeur de virtuel pour les raisons qu'évoque Fabien. Et bien
entendu l'exemple pour l'exemple ne dicte pas la bonne pratique.

Je ne pratique pas assez en C++ pour ne pas avoir de doute sur ce genre
de point, je voulais donc être certain d'avoir compris un point
"théorique". J'ai par contre suffisament d'expériences en C pour
comprendre l'importance d'un bonne pratique tel que celle enoncée par
Fabien.

Merci à vous deux.
Avatar
James Kanze
On Jul 25, 6:50 pm, Fabien LE LEZ wrote:
On Wed, 25 Jul 2007 18:34:02 +0200, hibakusha
:

Nécessaire ? je pensais que le destructeur ne devait être virtuel que
lorsque l'on jouait ensuite avec le polymorphisme ?


Oui. Mais en tant qu'auteur de la classe, tu ne peux pas être sûr de
ce que l'utilisateur fera avec.


Tu pourrais espérer qu'il utilise la classe à bonne échéance.
Sinon, ce n'est pas en faisant le destructeur virtuel que le
code va marcher.

La règle générale aujourd'hui est, je crois : si la classe doit
servir de base, le destructeur doit être soit virtuel, soit
protégé (afin qu'on ne peut pas faire delete à un pointeur à la
classe de base). N'empèche que std::iterator a bien un
destructeur public, tout le monde en dérive, et je n'ai jamais,
jamais entendu parler d'un problème à cet égard. La sémantique
de la classe est telle qu'il ne vient même pas à l'esprit d'en
vouloir un pointeur à elle.

Même si tu as les deux casquettes, tu finiras peut-être, au bout de
quelques transformations de code, par détruire un objet de la classe
de façon polymorphique, ayant oublié que tu n'as pas le droit de le
faire.


Si l'objet est polymorphique, oui, et il y a même des
compilateurs qui avertit si la classe a une fonction virtuelle,
mais que le destructeur n'est pas virtuel. Si la classe est
conçue pour servir de base pour des raisons autres que le
polymorphisme, comme c'est le cas de std::iterator, tout dépend.
(Dans le cas de std::iterator, moi, je lui aurais donné un
destructeur protégé. Mais dans la pratique, le fait que le
destructeur soit public ne me paraît pas être un gros problème
non plus.)

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Avatar
Fabien LE LEZ
On Thu, 26 Jul 2007 07:09:39 -0700, James Kanze
:

N'empèche que std::iterator a bien un destructeur public


Le standard suit des règles différentes : le programmeur est censé
connaître le standard, et savoir comment on utilise ses classes. Par
contre, on n'est pas censé connaître sur le bout des doigts les règles
d'utilisation d'une classe issue d'une autre bibliothèque.

1 2