I’m using visual studio 2008, c++, win32, no dot net.
I’ve got a problem with virtual functions that are called in the destructor of a parent.
For example, take the classes a and b. Class a has a virtual function called Hello(); When called, it prints hello.
Class b inherits from class a and also implements the function Hello. When called, it prints world.
In the destructor of class a the function Hello is called. When class b is deleted, the destructor of b is first called, then the destructor of a. In the destructor of a the function Hello is called, except the it’s the implementation associated with class a, not class b.
Code for this example below this line.
class a{
public:
virtual void Hello();
a();
~a();
};
a::a(){
};
a::~a(){
Hello();
}
void a::Hello(){
printf("hello\n");
}
class b:public a{
public:
virtual void Hello();
b();
~b();
};
b::b(){
}
b::~b(){
}
void b::Hello(){
printf("world\n");
}
int _tmain(int argc, _TCHAR* argv[]){
a* exampleA=new a();
b* exampleB=new b();
exampleA->Hello();
exampleB->Hello();
delete exampleA;
delete exampleB;
return 0;
}
And the output is:
hello
world
hello
hello
When I place a breakpoint in the destructor of class b, the __vfptr in the local variables
are as follows:
__vfptr
[0x0] 0x002314ce b::Hello(void)
When a step through and enter de destructor of class a, the __vfptr in the local variables has changed to:
__vfptr
[0x0] 0x0024c864 a::Hello(void)
This is normal I quess? And there is no (correct) way to call the b’s implementation of Hello inside the destructor of class a ?
The issue here is the order of destruction:
bis destroyeda.It wouldn’t be safe for
~a()to call methods (virtual ones) from the destroyedb, as such methods could refer/make use of class members insidebthat have already been destroyedI also recommend this article by Scott Meyers:
http://www.artima.com/cppsource/nevercall.html
Also, I subscribe to Mark B’s solution. Also Kerrek SB’s quote confirms this as standard, well defined behavior.