ryancheung ryancheung - 3 months ago 7
C++ Question

Polymorph ability of virtual function called in destructor of base class

#include <iostream>
#include <map>

using namespace std;
class Base
{
public:
int m_nValue;

Base()
{
}

virtual ~Base()
{
Clear();
}

virtual void Clear()
{
cout << "Destroy Base." << endl;
}
};

class Derived: public Base
{
public:
Derived()
{
}

void Clear() override
{
cout << "Destory Derived." << endl;
}
};

int main()
{
Derived* d = new Derived();
delete d;
}


This prints "Destroy Base.". I'm newbie in C++, anyone can tell me why this happends? Why not prints "Destory Derived."

Answer

When (just before) the body of a constructor for type T starts executing, the dynamic type of the object is adjusted to T.

This means that virtual calls will resolve as if the object was originally created of type T.

It's a pretty expensive mechanism, so it's there for a very important reason: to avoid calls down to a virtual function implementation m in a derived class D where the ┬╣assumptions of D::m have not yet been established. Such down-calls are a common source of bugs in e.g. Java. It can't happen in C++.

The last constructor body invoked is that of the most derived class, the class that was used for creation of the object. And so that's the dynamic type that the object ends up with.

Conversely, when the object is destroyed the opposite happens: a series of adjustments of dynamic type to ever more general type. Essentially, during execution of the body of the destructor for a class T, the object's dynamic type is T. Just as it was during execution of the body of some T constructor.


Notes:
┬╣ The context-independent assumptions of a member function of a class T is what can be assumed in general about the state of a T object, e.g. relationships among its member variable values. This is called the class invariant of T. So, the C++ dynamic type adjustment mechanism helps to ensure that only constructors and destructors have to deal with a not fully established class invariant: in C++ (but e.g. not in Java or C#) all other member functions can just blindly assume that the class invariant has been established.