OVH Cloud OVH Cloud

fonction membre virtuelle dans un destructeur

5 réponses
Avatar
Cyrille \cns\ Szymanski
Bonjour,

je cherche à appeler une fonction membre virtuelle dans un destructeur
mais cela ne fonctionne pas comme je l'aurais espéré.

struct A {
void print() { do_print(); }
~A() { do_print(); }
virtual void do_print() { cout << "A"; }
};

Dans print(), l'appel est bien fait à partir du pointeur virtuel do_print
alors que dans le destructeur l'appel se fait sur A::do_print().

C'est encore pire si do_print() est virtuelle pure, le compilateur ne
râle même pas.

struct B : public A {
void do_print() { cout << "B"; }
};

int main()
{
B b;
b.print();
// affiche BA
// alors que le corps de ~A() et de print() est le même
}

Quelqu'un peut-il m'expliquer les raisons de cela ?

J'utilise BCC 5.5.1


D'avance merci
--
_|_|_| CnS
_|_| for(n=0;b;n++)
_| b&=b-1; /*pp.47 K&R*/

5 réponses

Avatar
Cyrille \cns\ Szymanski
je cherche à appeler une fonction membre virtuelle dans un destructeur
mais cela ne fonctionne pas comme je l'aurais espéré.


"In constructors and destructor, the dynamic type of an object equates
its static type, meaning that the virtual fonction is statically
resolved to A::f." --Gabriel Dos Reis

C'est curieux.

--
_|_|_| CnS
_|_| for(n=0;b;n++)
_| b&=b-1; /*pp.47 K&R*/

Avatar
Fabien SK
Cyrille "cns" Szymanski wrote:
je cherche à appeler une fonction membre virtuelle dans un destructeur
mais cela ne fonctionne pas comme je l'aurais espéré.



"In constructors and destructor, the dynamic type of an object equates
its static type, meaning that the virtual fonction is statically
resolved to A::f." --Gabriel Dos Reis

C'est curieux.


D'un coté, c'est logique que ça pose des problèmes. Exemple:

class Base
{
public:
~Base()
{
DoIt();
}
protected:
virtual void DoIt(){}
};

class Fille:public Base
{
protected:
void DoIt(){ std::cout << m_Texte << std::endl; }
std::string m_Texte;
};

L'ordre d'appel est:
- destructeur de "Fille"
- destructeur des membres de "Fille"
- destructeur de "Base"

Quand le destructeur de "Base" appelle "DoIt" (donc "Fille::DoIt"), hors
"Fille" et ses membres ont déjà été détruits, d'où catastrophe.


Avatar
Jorge Rivera
Avez vous essayez de declarer le destructeur de A vituel?

Je crois que un destructeur virtuel n'appelera pas A::do_print(), mais
do_print() de l'object dynamique...

Je veut dire (excusez mon francais...):

class A{
public:
A(){}
virtual void ~A(){ do_print(); }
public:
void print(){ do_print(); }
private:
virtual void do_print(){ cout<<"A"; }
};

Cyrille "cns" Szymanski wrote:
Bonjour,

je cherche à appeler une fonction membre virtuelle dans un destructeur
mais cela ne fonctionne pas comme je l'aurais espéré.

struct A {
void print() { do_print(); }
~A() { do_print(); }
virtual void do_print() { cout << "A"; }
};

Dans print(), l'appel est bien fait à partir du pointeur virtuel do_print
alors que dans le destructeur l'appel se fait sur A::do_print().

C'est encore pire si do_print() est virtuelle pure, le compilateur ne
râle même pas.

struct B : public A {
void do_print() { cout << "B"; }
};

int main()
{
B b;
b.print();
// affiche BA
// alors que le corps de ~A() et de print() est le même
}

Quelqu'un peut-il m'expliquer les raisons de cela ?

J'utilise BCC 5.5.1


D'avance merci


Avatar
Fabien LE LEZ
On Fri, 02 Jan 2004 17:10:38 GMT, Jorge Rivera
wrote:

Je crois que un destructeur virtuel n'appelera pas A::do_print(), mais
do_print() de l'object dynamique...


Non. L'"objet dynamique" n'existe déjà plus.

--
;-)

http://www.gotw.ca/gotw/063.htm
http://www.gotw.ca/gotw/067.htm#2

Avatar
Cyrille \cns\ Szymanski
Avez vous essayez de declarer le destructeur de A vituel?

Je crois que un destructeur virtuel n'appelera pas A::do_print(), mais
do_print() de l'object dynamique...


J'ai essayé mais malheureusement cela ne fonctionne pas.

Tout est clair à présent que Fabien m'a dit de regarder l'ordre d'appel des
destructeurs.

--
_|_|_| CnS
_|_| for(n=0;b;n++)
_| b&=b-1; /*pp.47 K&R*/