Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum. Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

Sujet : Une méthode virtuelle appelée depuis un destructeur n'est pas héritée!? [ Divers / Débutant(e) ] (Forman)

vendredi 15 juin 2007 à 21:58:32 | Une méthode virtuelle appelée depuis un destructeur n'est pas héritée!?

Forman

Bonjour(soir) à tous,

je viens de me mettre au C++ et à GLUT et je bute sur un problème que je n'arrive pas à m'expliquer. D'abord, voilà le code en question (qui permettra de clarifier mes explications par la suite je l'espère):
template<class THANDLE=int,unsigned int INVALID_HANDLE=0> class Handled{
protected:
THANDLE Handle;

Handled(){
Handle=INVALID_HANDLE;
}

~Handled(){
if (handleAllocated())
deleteHandle();
}

void handleNeeded(){
if (!handleAllocated())
createHandle();
};

virtual void createHandle()=0;
virtual void deleteHandle()=0;
public:
int handleAllocated(){
return Handle!=INVALID_HANDLE;
};

THANDLE getHandle(){
handleNeeded();
return Handle;
};

void recreateHandle(){
if (handleAllocated()){
deleteHandle();
Handle=INVALID_HANDLE;
handleNeeded();
}
};
};

class Window: public Handled<int,0>{
protected:
char *Name;
Window *Parent;
int X,Y,Width,Height;

void call(){
glutSetWindow(getHandle());
};

void createHandle();
void deleteHandle();
public:
Window(char *name,int x=100,int y=100,int width=320,int height=240):Name(name),Parent(NULL),X(x),Y(y),Width(width),Height(height){
handleNeeded();
};

Window(char *name,Window *parent,int x=80,int y=60,int width=160,int height=120):Name(NULL),Parent(parent),X(x),Y(y),Width(width),Height(height){
handleNeeded();
};
}

void Window::createHandle(){
/* Code qui crée une fenêtre avec GLUT et stocke l'index retourné dans Handle */
};

void Window::deleteHandle(){
/* Code qui crée une fenêtre avec GLUT et stocke l'index retourné dans Handle */
};

Donc voilà j'ai une classe de base qui sert à dériver des sous-classes encapsulant des objets systèmes auxquels on accède via une série d'API et un "Handle" qui est typiquement un entier. Le template avec THANDLE et INVALID_HANDLE sert à faire la distinction entre les objets systèmes qui sont liés à un entier signé (fenêtres GLUT par exemple) et ceux qui sont liés à un entier non signé (identifiants de texture OpenGl par exemple).

Les appels aux API servant à allouer/libérer les Handle systèmes en question sont définis dans la classes descendante en surchargeant les méthodes virtuelles pures createHandle et deleteHandle. Tout se passe bien dans les constructeurs qui appellent (directement ou indirectement) createHandle, la méthode descendante est appelée et mon objet système est bien créé.

Mais, et ça je n'arrive pas à l'expliquer, lorsqu'une instance de la classe descendante est détruite, ce n'est pas le cas : c'est la méthode de base deleteHandle qui est appelée... générant bien évidemment une exception "pure virtual function call". J'ai naïvement essayé de rendre le destructeur virtuel, voire de passer par un pointeur sur l'instance en espérant court-circuiter le typage à la compilation (car c'est de ça qu'il s'agit je suppose) rien n'y fait.

Est-ce une spécification du C++ (toute la doc que j'ai lue jusque-là n'en faisait pas mention en tout cas)? Est-ce que ça vient de ce que ma classe est une template?

Merci d'avance de votre aide.


samedi 16 juin 2007 à 00:28:48 | Re : Une méthode virtuelle appelée depuis un destructeur n'est pas héritée!?

luhtor

Window * pWindow = new Window();
Handled * pHandled = pWindow;
delete pHandled;

Si ton destructeur n'est pas virtuel, c'est le destructeur de pHandled qui sera appelé dans ce cas.

delete pWindow <= ici le destructeur de Window.

Donc ca coute rien de toujours mettre le destructeur virtuel:
virtual ~Handled();

Mais ya aucun pb. Sauf que toi il semble que tu l'ais mis virtuel pure, ce qui n'a évidemment aucun sens ici, mais c'est faisable dans certain cas.

samedi 16 juin 2007 à 01:02:30 | Re : Une méthode virtuelle appelée depuis un destructeur n'est pas héritée!?

aardman

Membre Club
Réponse acceptée !
Salut,
Au moment de l'appel du destructeur de ta classe de base, le destructeur de ta classe derivée à déja été appelé, et comme un appel virtuel peut utiliser les données de ta classe derivée, il est interdit ici.
Même raisonnement pour le constructeur, si tu appeles une fonction virtuelle depuis le constructeur de ta classe de base, ca signifierait qu'une methode de ta classe derivée peut etre appelée avant que le constructeur de cette meme classe ai été appelé, ce qui est dangereux puisque les données de ta classe derivée n'ont pas encore été initialisées.



samedi 16 juin 2007 à 10:52:27 | Re : Une méthode virtuelle appelée depuis un destructeur n'est pas héritée!?

Forman

Bonjour,

Merci d'avoir pris la peine de répondre.

@luthor: en fait je n'ai guère besoin de faire un destructeur virtuel, sachant que ma classe Handled est seulement là pour m'éviter d'avoir à retaper 10 lignes à chaque nouvelle classe encapsulante. Mais j'y penserai, c'est plus prudent.

@aardman: merci, effectivement l'argument est imparable.



Cette discussion est classé dans : int, handle, void, window, deletehandle


Répondre à ce message

Sujets en rapport avec ce message

void et int [ par xionoxid ] SalutC koi la difference entre unvoid a;et int a; ?? équation et tableaux [ par cabarrus ] je ne trouve pas l'erreur dans mon programme?#include#includeint deltanul(int);float deltainf(float);float deltasup(float);void main(void){float a,b,c Fch. Header :: CONIO.H [ par TontOnDuWeb ] Pour ce que ca interesse (avec vc++ les fonctions suivantes e sont pas incluse (du moins je crois...))>>#if !defined(__CONIO_H)#define __CONIO_H#if !d Probleme de compilation Multithread [ par TwinSidE ] Bonjour,J'ai une classe de ce type :class C_ClientServer{public:    C_ClientServer(void);    ~C_ClientServer(void);    bool StartServerListening(char* class.... [ par Tautau ] voila j'ai un petit prob lors de ma compilation et j'ai un test dessus lundi :#include "conio.h"#include "iostream.h"class C_Tableau{ private: Snake tsssssssssss aidez moiiiiiiii [ par AmK ] Salut ,Je suis en train de coder un snake et la je crois avoir bien compris le principe de l'algo mais niveau code ça foire je sais pas pourquoi voila pb de Z-buffer ac openGL -> Help! [ par Arnaud16022 ] bonjour tt le monde!quelqun pourrait me dire pourqoui le Z-buffer marche pas?pasque le dernier (4ème) triangle dessiné apparait tjs au dessus, meme s' pb de compilation [ par norton ] bonjour, je desir compiler le code suivant mais j'ai une erreur.mon code :#include #include #include void Display();void Reshape(int,int);int main( in une fiche de renseignement [ par cabarrus ] je cherche à faire un programme qui demande des renseignements pour pouvoir ensuite les affiché comme une fiche d'identité!!!voici monprogramme mais m Probleme fonctions [niveau debutant] [ par zzzzzz ] en fait je voulais faire une applic qui nous demande un nombre de part et de fin si on met par exemple 2 et 7 sa ecrira 234567 grace a une boucle. le


Nos sponsors

Sondage...

CalendriCode

Juillet 2009
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
2728293031  

Consulter la suite du CalendriCode

Téléchargements

Logiciels à télécharger sur le même thème :

Comparez les prix Nouvelle version

Photothèque Nouveau !



Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés
Temps d'éxécution de la page : 0,312 sec

Google Coop CodeS-SourceS Google Coop CodeS-SourceS


Certaines images présentes sur le site (notament certains avatars) sont issues des collections IconShock, donc si vous souhaitez utiliser ces icons vous devez les acheter, ne les copiez pas et ne utilisez pas dans vos sites et applications sans les avoir commandé.