GNT sans publicité, site mobile, fonctionnalitées exclusives...

destructeurs virtuels et héritage

Le
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')
Lire les 14 réponses

Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses Page 1 / 3
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Alp Mestan
Le #309201
Edrusb wrote:
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.



Il est nécessaire que toute classe dont une autre va dériver possède un
destructeur virtuel. Seule la classe tout en bas de la hiérarchie, dont
aucune autre va dériver, peut ne pas avoir de destructeur virtuel.
Le destructeur virtuel _DOIT_ être implémenté pour toute classe mère,
afin de ne pas avoir de fuite lors de l'utilisation du polymorphisme par
le biais d'une classe de base.

Alp

James Kanze
Le #309161
On Jul 22, 10:30 am, Edrusb
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 virtu els
aussi:


La virtualité d'une fonction s'hérite. Si le destructeur de
n'importe quelle classe de base est déclaré virtuel, le
destructeur de la classe en question est aussi virtuel, même
s'il n'est pas déclaré tel, et même s'il est généré
implicitement par le compilateur.

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;


Tout à fait. Sauf que la risque n'est pas une fuite de mémoire,
mais plutôt un comportement indéfini.

--
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

Alp Mestan
Le #309160
James Kanze wrote:
On Jul 22, 10:30 am, Edrusb
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:


La virtualité d'une fonction s'hérite. Si le destructeur de
n'importe quelle classe de base est déclaré virtuel, le
destructeur de la classe en question est aussi virtuel, même
s'il n'est pas déclaré tel, et même s'il est généré
implicitement par le compilateur.


Ah j'aurais pensé qu'il y aurait exception ici.
Cependant pour échapper à des comportements indéfinis, il vaut mieux
redéfinir un destructeur (virtuel si la classe sera dérivée à son tour).



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;


Tout à fait. Sauf que la risque n'est pas une fuite de mémoire,
mais plutôt un comportement indéfini.

--
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




Edrusb
Le #309158
James Kanze wrote:
[...]

Tout à fait. Sauf que la risque n'est pas une fuite de mémoire,
mais plutôt un comportement indéfini.




Merci à tous les deux pour vos réponses.


--
Edrusb
(supprimer le 'a')


James Kanze
Le #309156
On Jul 22, 11:22 am, Alp Mestan
James Kanze wrote:
On Jul 22, 10:30 am, Edrusb
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 (all oué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 vi rtuels
aussi:


La virtualité d'une fonction s'hérite. Si le destructeur de
n'importe quelle classe de base est déclaré virtuel, le
destructeur de la classe en question est aussi virtuel, même
s'il n'est pas déclaré tel, et même s'il est généré
implicitement par le compilateur.


Ah j'aurais pensé qu'il y aurait exception ici.


Pourquoi ?

Cependant pour échapper à des comportements indéfinis, il vaut mieux
redéfinir un destructeur (virtuel si la classe sera dérivée à son tour).


Encore, pourquoi ? La seule raison que je vois, c'est
l'habituelle, qu'on définit toujours un destructeur, même vide,
afin d'éviter qu'il soit inline.

--
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



Publicité
Suivre les réponses
Poster une réponse
Anonyme