Héritage et destructeur

Héritage et destructeur - C++ - Programmation

Marsh Posté le 17-04-2003 à 04:12:45    

salut,
j'ai un petit problème: j'ai une classe mère Gate qui est étendue par un certain nombre de classes. J'ai un destructeur définis dans ma classe mère et dans certaines classes filles, pour faire qlq delete.
Bon, mon problème est que si je fais ca:

Code :
  1. Gate *and_1 = new ANDGate();
  2. //blah blah
  3. delete and_1;

 
tout marche comme il faut jusqu'au delete: c'est le destructeur de Gate qui est appelé, pas de celui ANDGate.
 
Est-ce que quelqu'un sait comment contourner ce problème (à part le  delete (ANDGate*)and_1; qui marche mais qui est pas top)?
 
merci


---------------
"La Terre est le berceau de l'humanité, mais on ne passe pas toute sa vie au berceau." - Konstantine Tsiolkovski
Reply

Marsh Posté le 17-04-2003 à 04:12:45   

Reply

Marsh Posté le 17-04-2003 à 05:45:17    

Il est virtuel ton destructeur ?
 
LeGreg


---------------
voxel terrain render engine | animation mentor
Reply

Marsh Posté le 17-04-2003 à 08:29:37    

deltaden a écrit :

salut,
j'ai un petit problème: j'ai une classe mère Gate qui est étendue par un certain nombre de classes. J'ai un destructeur définis dans ma classe mère et dans certaines classes filles, pour faire qlq delete.
Bon, mon problème est que si je fais ca:

Code :
  1. Gate *and_1 = new ANDGate();
  2. //blah blah
  3. delete and_1;

 
tout marche comme il faut jusqu'au delete: c'est le destructeur de Gate qui est appelé, pas de celui ANDGate.
 
Est-ce que quelqu'un sait comment contourner ce problème (à part le  delete (ANDGate*)and_1; qui marche mais qui est pas top)?
 
merci


A priori si ton objet est de type Gate je vois pas pkoi ce serait le destructeur de ANDGate qui serait appelé...:??:
Pkoi tu déclares pas directement ton objet en tant qu'ANDGate en le castant en Gate quand tu en as besoin?

Reply

Marsh Posté le 17-04-2003 à 08:34:33    

par ce que c'est pour faire du polymorphisme qui passe par des pointeurs de classe mère. L'intéret est donc de ne pas avoir à faire de cast et on ne se soucie pas du type réel de l'objet. Les mécanismes virtuels sont là.

Reply

Marsh Posté le 17-04-2003 à 08:36:05    

Ca sent le destructeur de Gate pas virtuel ça :o


---------------
brisez les rêves des gens, il en restera toujours quelque chose...  -- laissez moi troller sur discu !
Reply

Marsh Posté le 17-04-2003 à 08:37:38    

kadreg a écrit :

Ca sent le destructeur de Gate pas virtuel ça :o

mais que de perspicacité aujourd'hui  [:xp1700]

Reply

Marsh Posté le 17-04-2003 à 08:39:04    

J'ai rien dit...'suis pas au niveau là on dirait...:lol:
Rassurez-moi, ct pas tout à fait idiot qd même...?
[Edit]

Citation :

J'ai un destructeur définis dans ma classe mère et dans certaines classes filles


Ca risque pas de poser pb s'il le passe en virtuel?
(Si je dis une connerie tapez pas trop fort...:D)


Message édité par skeye le 17-04-2003 à 08:41:46
Reply

Marsh Posté le 17-04-2003 à 08:40:13    

t'as qu'à dire que t'es mal réveillé    [:spamafote]

Reply

Marsh Posté le 17-04-2003 à 08:47:56    

++Taz a écrit :

t'as qu'à dire que t'es mal réveillé    [:spamafote]  


voir edit...mais si c encore une connerie je pars de suite chercher un cours de c++ moi (ca faisait un moment que j'y avais plus touché, mais pdt 6 mois faut que je m'y remette, alors ce sera pas perdu!).

Reply

Marsh Posté le 17-04-2003 à 08:49:30    

skeye a écrit :


Ca risque pas de poser pb s'il le passe en virtuel?


 
Tant qu'il est pas virtuel pur, non.
 
Au fait, c'est possible un destructeur virtuel pur ?


---------------
brisez les rêves des gens, il en restera toujours quelque chose...  -- laissez moi troller sur discu !
Reply

Marsh Posté le 17-04-2003 à 08:49:30   

Reply

Marsh Posté le 17-04-2003 à 08:50:23    

kadreg a écrit :


 
Tant qu'il est pas virtuel pur, non.
 
Au fait, c'est possible un destructeur virtuel pur ?


bon, c'est décidé, ce matin c'est révisions! :pt1cable:

Reply

Marsh Posté le 17-04-2003 à 08:51:22    

va te chercehr un cours. totues les classes meres ou filles on un destrcuteur. le destructeur des classe filles appellent naturellement le destructeur de la classe mère. le porblème c'est qu'avec un Mere* pointant vers une instance de Fille (ouhla) l'appel du destructeur (par delete) se contente par défaut d'appeler le destructeur de Mere (normal). il faut donc rajouter le mécanisme d'indirection virtuel pour que ça soit le destructeur du type réel de l'objet pointé qui soit appelé

Reply

Marsh Posté le 17-04-2003 à 08:56:35    

++Taz a écrit :

va te chercehr un cours. totues les classes meres ou filles on un destrcuteur. le destructeur des classe filles appellent naturellement le destructeur de la classe mère. le porblème c'est qu'avec un Mere* pointant vers une instance de Fille (ouhla) l'appel du destructeur (par delete) se contente par défaut d'appeler le destructeur de Mere (normal). il faut donc rajouter le mécanisme d'indirection virtuel pour que ça soit le destructeur du type réel de l'objet pointé qui soit appelé


C'est ça qui n'apparait pas (ou plus...) dans un seul recoin de ma cervelle...Le reste ca allait!

Reply

Marsh Posté le 17-04-2003 à 08:57:05    

kadreg a écrit :


Au fait, c'est possible un destructeur virtuel pur ?


 
Après test, non [:ddr555]


---------------
brisez les rêves des gens, il en restera toujours quelque chose...  -- laissez moi troller sur discu !
Reply

Marsh Posté le 17-04-2003 à 09:02:39    

pourquoi? par ce que toutes classe doit avoir un constructeur et un destructeur.

Reply

Marsh Posté le 17-04-2003 à 09:33:04    

Au cas où certains auraient besoin comme moi de se raffraichir la mémoire, l'explication est ici:
http://casteyde.christian.free.fr/ [...] x3673.html
[edit]
Dans ma tête n'existaient plus que les virtuelles pures...Ce qui explique ma question!


Message édité par skeye le 17-04-2003 à 09:34:39
Reply

Marsh Posté le 17-04-2003 à 09:38:45    

kadreg a écrit :


Après test, non [:ddr555]


 
pas besoin de test:
le destructeur de la classe mere est appelé
quoi qu'il arrive. Le minimum que tu puisses
faire c'est de ne rien faire pendant la destruction.
(un destructeur virtuel vide).
 
LeGreg


---------------
voxel terrain render engine | animation mentor
Reply

Marsh Posté le 17-04-2003 à 09:43:10    

kadreg a écrit :


 
Après test, non [:ddr555]


 
Si c'est possible ;)
 
Il faut faire un destructeur virtuel pur avec une implémentation.
 
Un truc du genre :
 

Code :
  1. class machin
  2. {
  3. public:
  4.    virtual ~machin() = 0;
  5. };
  6. machin::~machin()
  7. {}


Message édité par Kristoph le 17-04-2003 à 09:44:59
Reply

Marsh Posté le 17-04-2003 à 09:45:44    

Kristoph a écrit :


 
Si c'est possible ;)
 
Il faut faire un destructeur virtuel pur avec une implémentation.
 
Un truc du genre :
 

Code :
  1. class machin
  2. {
  3. public:
  4.    virtual ~machin() = 0;
  5. };
  6. machin::~machin()
  7. {}




Dans ma tête c'est contradictoire comme expression ça... :heink:


Message édité par skeye le 17-04-2003 à 09:46:14
Reply

Marsh Posté le 17-04-2003 à 09:48:55    

ça l'est!

Reply

Marsh Posté le 17-04-2003 à 09:51:17    

++Taz a écrit :

ça l'est!


Première fois que je dis pas une connerie de la journée...en progrès!:D

Reply

Marsh Posté le 17-04-2003 à 10:28:20    

++Taz a écrit :

ça l'est!


 
[:totoz] (je me le garde au chaud pour faire un questionnaire de C++ pour les entretiens d'embauche)


---------------
brisez les rêves des gens, il en restera toujours quelque chose...  -- laissez moi troller sur discu !
Reply

Marsh Posté le 17-04-2003 à 10:36:29    

kadreg a écrit :


 
[:totoz] (je me le garde au chaud pour faire un questionnaire de C++ pour les entretiens d'embauche)


ca paye bien? je sais répondre... :o

Reply

Marsh Posté le 17-04-2003 à 14:08:19    

ben oui, en effet, je l'avais pas déclarée virtuelle.
 
je commence en C++ là, alors il y a qlqs trucs où je suis un peu paumé...si je pose de bête question, c'est pas ma faute... :cry:  
 
à+ et merci  :jap:


---------------
"La Terre est le berceau de l'humanité, mais on ne passe pas toute sa vie au berceau." - Konstantine Tsiolkovski
Reply

Marsh Posté le 17-04-2003 à 20:09:22    

skeye a écrit :


Dans ma tête c'est contradictoire comme expression ça... :heink:


 
Efficient C++ seconde edition. Testé à l'instant avec g++ 2.96. Ça marche très bien.
 
J'aimerais bien faire le test aussi avec gcc 3.2 mais j'ai pas ça sous la main maintenant. Voici le code :
 

Code :
  1. #include <iostream>
  2. using namespace std;
  3. class machin
  4. {
  5.     public:
  6.        virtual ~machin() = 0;
  7. };
  8.  
  9.  
  10. machin::~machin()
  11. {
  12. cout << "~machin()\n";
  13. }
  14. class autre : public machin
  15. {
  16.     public:
  17.         virtual ~autre();
  18. };
  19. autre::~autre()
  20. {
  21. cout << "~autre()\n";
  22. }
  23. int main()
  24. {
  25. // machin * a;
  26. autre * b;
  27. // a = new machin;  Compile pas
  28. b = new autre;
  29. // delete a;
  30. delete b;
  31. return 0;
  32. }


 
Et le resultat :

Code :
  1. [kristoph@vvardenfell c++]$ g++ -W -Wall -ansi -pedantic abstrait.cpp -o abstrait
  2. [kristoph@vvardenfell c++]$ ./abstrait
  3. ~autre()
  4. ~machin()


Reply

Marsh Posté le 17-04-2003 à 20:15:46    

c'est un bug. comment le destructeur de machin et constate les dégats. je regarde s'il y a des rapports la dessus.

Reply

Marsh Posté le 17-04-2003 à 20:18:07    

++Taz a écrit :

c'est un bug. comment le destructeur de machin et constate les dégats. je regarde s'il y a des rapports la dessus.


 
Je ne comprends pas ce que tu veux dire par la ?

Reply

Marsh Posté le 17-04-2003 à 20:29:26    

je sais pas, conceptuellement une virtuelle pure implémentée, ça n'a pas de sens. L'un des inetert des fonctions virtuelles pures, c'est aussi de réduir le temps de compilation en différent l'implémentation. et je n'ai jamais vu ça. je cherche une référence pour faire le point
 
eidt: je trouve pas.


Message édité par Taz le 17-04-2003 à 20:34:20
Reply

Marsh Posté le 17-04-2003 à 20:35:11    

C'est clair que définir une fonction comme virtuelle pure correspond à prévenir le compilo qu'on ne va pas donner de corps à cette fonction dans cette classe mais dans les classes héritantes ...
 
Normalement, c'est à cause de ces déclarations que le compilo peut savoir qu'une classe est abstraite et qu'on ne peut donc pas l'instancier ...
 
Implémenter une fonction est forcément illogique ... Autant la mettre simplement en virtuel, si c'est pour lui donner un corps ...


---------------
last.fm
Reply

Marsh Posté le 17-04-2003 à 20:37:50    

theShOcKwAvE a écrit :

C'est clair que définir une fonction comme virtuelle pure correspond à prévenir le compilo qu'on ne va pas donner de corps à cette fonction dans cette classe mais dans les classes héritantes ...
 
Normalement, c'est à cause de ces déclarations que le compilo peut savoir qu'une classe est abstraite et qu'on ne peut donc pas l'instancier ...
 
Implémenter une fonction est forcément illogique ... Autant la mettre simplement en virtuel, si c'est pour lui donner un corps ...


 
Explication de Meyers sous la forme d'une question :
 
"Comment faire une classe abstraite sans aucune méthode ?"
 
Réponse : Un destructeur virtuel pur.

Reply

Marsh Posté le 17-04-2003 à 20:41:29    

C'est vrai que ca aurait pu être un problème con ... :D
 
Mais ca pourrait aussi être géré en tant que cas particulier ...
 
Java a l'avantage d'être explicite : interface ...


---------------
last.fm
Reply

Marsh Posté le 17-04-2003 à 20:42:07    

oui mais il faut donner une implémentation, sur.
 
 
je viens de parler avec une pointure, et apparemment rien n'empeche d'implementer une virtuelle pure. cette personne est d'accord que cela n'a aucun sens et devrait etre interdit (il y a eu des proposals dans ce sens). son sentiment, que je partage, est que si une fonction virutelle pure f est munie d'une implémentation, évidemment la pureté est violée (ouh la!) et qu'il vaut mieux faire de cette manière
 

Code :
  1. class Base
  2.     {
  3.      void Defaut() { ... }
  4.      virtual void f()= 0;
  5.     };
  6.     class Derivee
  7.     {
  8.      void f() { Defaut(); }
  9.     };

Reply

Marsh Posté le 17-04-2003 à 20:43:15    

theShOcKwAvE a écrit :

C'est vrai que ca aurait pu être un problème con ... :D
 
Mais ca pourrait aussi être géré en tant que cas particulier ...
 
Java a l'avantage d'être explicite : interface ...

je suis d'accord, c'est une mauvaise permission. Utiliser cette liberté du C++ sème la confusion

Reply

Marsh Posté le 17-04-2003 à 20:49:34    

pour la rendre abstraite il suffit de ne pas lui donner
de vtable genre "__declspec(novtable)" (c'est pas une fonction
du standard mais comme "__declspec(deprecated)" ca peut s'averer utile).
Dans ce cas elle peut etre abstraite et avoir un corps
defini pour chaque fonction virtuelle.
(par contre tu ne paies pas le cout de la table
virtuelle pour chaque classe abstraite).
 
LeGreg


Message édité par LeGreg le 17-04-2003 à 20:53:04

---------------
voxel terrain render engine | animation mentor
Reply

Marsh Posté le 17-04-2003 à 20:50:02    

Kristoph a écrit :


 
Explication de Meyers sous la forme d'une question :
 
"Comment faire une classe abstraite sans aucune méthode ?"
 
Réponse : Un destructeur virtuel pur.

ça serait mieux des constructeurs protected il me semble

Reply

Marsh Posté le 17-04-2003 à 21:06:27    

++Taz a écrit :

ça serait mieux des constructeurs protected il me semble


 
Je sais pas, faudrait que je relise le livre, mais je ne l'ai pas sous la main. Scott Meyers c'est aussi une grosse pointure du C++ il me semble ;)

Reply

Marsh Posté le 17-04-2003 à 21:08:25    

certes. mais beaucoup s'accord à dire qu'un destructeur virtuel pure n'a vraiment aps de sens, puisque que chaque classe est muni d'un destructeur.   [:spamafote]

Reply

Marsh Posté le 23-07-2012 à 12:17:54    

deltaden a écrit :

salut,
j'ai un petit problème: j'ai une classe mère Gate qui est étendue par un certain nombre de classes. J'ai un destructeur définis dans ma classe mère et dans certaines classes filles, pour faire qlq delete.
Bon, mon problème est que si je fais ca:

Code :
  1. Gate *and_1 = new ANDGate();
  2. //blah blah
  3. delete and_1;

 
tout marche comme il faut jusqu'au delete: c'est le destructeur de Gate qui est appelé, pas de celui ANDGate.
 
Est-ce que quelqu'un sait comment contourner ce problème (à part le  delete (ANDGate*)and_1; qui marche mais qui est pas top)?
 
merci


 
je pense que les reponses que je vois sur cette page ne repondent pas tout a fait a la question qui est posee
 
si j'ai bien compris dans ton exemple ANDGate derive de la classe Gate,
 
tu cree une instance de la classe derivee ANDGate, que tu stockes dans un pointeur de la classe mere(par exemple pour lister plusieurs type de gate (ORGate, ANDGate, XORGate etc...) dans la meme liste de GATE.
 
le probleme c'est que lorsque tu veux detruire les elements de la liste de GATE, tu as perdu le type exact des tes "GATE"
 
tu peux faire appel au destructeur de la classe mere, mais son probleme c'est qu'il n'est pas complet, il va detruire les attributs communs aux GATE mais la memoire vive restera "polluee" par les attributs supplementaires de la classe derivee ANDGate.
 
dans l'autre sens quand on fait appel au destructeur d'une classe fille, celui de la classe mere est automatiquement appele, mais ce cas est le cas inverse et il est plus delicat
 
j'ai pas de solution absolue a ce probleme, tu peux par exemple creer une structure
 
enum TypeGATE
{
AND,
OR,
XOR
}
 
 
struct GATE_struct
{
GATE* pointeur;
TypeGATE type_gate;
}
 
ensuite ca donne  
Gate *and_1 = new ANDGate();
GATE_struct ma_gate;
ma_gate.pointeur = and_1;
ma_gate.TypeGate = AND;
 
ensuite pour faire appel au destructeur tu fais
switch(ma_gate.TypeGate)
case AND:
delete (ANDGate *)(and_1);
 
c'est lourd et moche, j'espere que quelqu'un aura mieux

Reply

Marsh Posté le 23-07-2012 à 12:20:07    

deltaden a écrit :

salut,
j'ai un petit problème: j'ai une classe mère Gate qui est étendue par un certain nombre de classes. J'ai un destructeur définis dans ma classe mère et dans certaines classes filles, pour faire qlq delete.
Bon, mon problème est que si je fais ca:

Code :
  1. Gate *and_1 = new ANDGate();
  2. //blah blah
  3. delete and_1;

 
tout marche comme il faut jusqu'au delete: c'est le destructeur de Gate qui est appelé, pas de celui ANDGate.
 
Est-ce que quelqu'un sait comment contourner ce problème (à part le  delete (ANDGate*)and_1; qui marche mais qui est pas top)?
 
merci


 
je pense que les reponses que je vois sur cette page ne repondent pas tout a fait a la question qui est posee
 
si j'ai bien compris dans ton exemple ANDGate derive de la classe Gate,
 
tu cree une instance de la classe derivee ANDGate, que tu stockes dans un pointeur de la classe mere(par exemple pour lister plusieurs type de gate (ORGate, ANDGate, XORGate etc...) dans la meme liste de GATE.
 
le probleme c'est que lorsque tu veux detruire les elements de la liste de GATE, tu as perdu le type exact des tes "GATE"
 
tu peux faire appel au destructeur de la classe mere, mais son probleme c'est qu'il n'est pas complet, il va detruire les attributs communs aux GATE mais la memoire vive restera "polluee" par les attributs supplementaires de la classe derivee ANDGate.
 
dans l'autre sens quand on fait appel au destructeur d'une classe fille, celui de la classe mere est automatiquement appele, mais ce cas est le cas inverse et il est plus delicat
 
j'ai pas de solution absolue a ce probleme, tu peux par exemple creer une structure
 
enum TypeGATE
{
AND,
OR,
XOR
}
 
 
struct GATE_struct
{
GATE* pointeur;
TypeGATE type_gate;
}
 
ensuite ca donne  
Gate *and_1 = new ANDGate();
GATE_struct ma_gate;
ma_gate.pointeur = and_1;
ma_gate.TypeGate = AND;
 
ensuite pour faire appel au destructeur tu fais
switch(ma_gate.TypeGate)
case AND:
delete (ANDGate *)(and_1);
 
c'est lourd et moche, j'espere que quelqu'un aura mieux

Reply

Marsh Posté le 23-07-2012 à 15:33:13    

d'une part, j'espère qu'en 9 ans, l'auteur aura trouvé une solution à son problème.
D'autre part, ta proposition est mauvaise : c'est typiquement un cas où il faut passer par de la virtualité comme proposé dans les réponses plus haut
 
Edit : et pour ce qui est du problème d'empêcher l'instanciation de la classe mère (qui a conduit à la dérive sur le droit ou non d'implémenter une virtuelle pure), il y a une solution plus élégante : déclarer les constructeurs de la classe mère en protected.


Message édité par theshockwave le 23-07-2012 à 15:34:49

---------------
last.fm
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed