cs_Forman
Messages postés600Date d'inscriptionsamedi 8 juin 2002StatutMembreDernière intervention 6 avril 2010
-
15 juin 2007 à 21:58
cs_Forman
Messages postés600Date d'inscriptionsamedi 8 juin 2002StatutMembreDernière intervention 6 avril 2010
-
16 juin 2007 à 10:52
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();
};
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?
cs_aardman
Messages postés1905Date d'inscriptionmercredi 22 janvier 2003StatutMembreDernière intervention17 septembre 20123 16 juin 2007 à 01:02
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.
cs_Forman
Messages postés600Date d'inscriptionsamedi 8 juin 2002StatutMembreDernière intervention 6 avril 20101 16 juin 2007 à 10:52
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.