Vfptr / vftable changes base type when class destructor calls parent destructor

I am using visual studio 2008, c ++, win32, no network point.

I have a problem with virtual functions being called in the parent's destructor. For example, take classes a and b. Class a has a virtual function Hello (); When called, it prints hello.

Class b inherits from class a and also implements the Hello function. When called, it prints the world.

In the destructor of class a, the Hello function is called. When class b is removed, the destructor of b is called first, then the destructor of a. In the destructor of the function, the Hello function is called, with the exception of its implementation associated with class a, not class b.

The code for this example is 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 result:

hello
world
hello
hello

      

When I put a breakpoint in the destructor of class b, the __vfptr in local variables are as follows:

__vfptr
  [0x0]    0x002314ce b::Hello(void)

      

When step and enter the destructor of class a, __vfptr in local variables changed to:

__vfptr
  [0x0]   0x0024c864 a::Hello(void)

      

Is this ok I don't know? And there is no (correct) way to call the b Hello implementation inside the destructor of class a?

+3


source to share


3 answers


Here we are talking about the order of destruction:

  • first the derived class is b

    destroyed
  • then the base class a

    . It would not be possible to ~a()

    call methods (virtual) from destroyed b

    , since such methods could reference / use class members inside b

    that were already destroyed.


I also recommend this article by Scott Meyers: http://www.artima.com/cppsource/nevercall.html

Also, I subscribe to Mark B's solution. Also quote from Kerrek SB confirms this as standard, well-defined behavior.

+2


source


It is right. There is a

no path to b in the destructor Hello

. The same is true for constructors.



If you really want something called polmorphically on destruction, you can forcefully destroy the two-ohaz with a private / protected destructor and a public destruction method that calls the virtual function first and then self-destructs.

+1


source


According to 12.7 / 4,

When a virtual function is called directly or indirectly from a constructor or from a destructor, [...] the called function is the final override in the constructor or destructor class, and not as one of them, the derived class

and hence the behavior is well defined and you call the member function in the class itself and there is no dynamic dispatch.

+1


source







All Articles