1
#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."

ryancheung
  • 2,999
  • 3
  • 24
  • 25
  • @Cheersandhth.-Alf - As far as I can see, that's a question (admittedly a poor one) with the same fundamental issue, and the accepted answer is also an answer to this question. That said, there are plenty of other "behaviour of virtual calls in a destructor" questions - if you can spot a better one, please go for it :) – Oliver Charlesworth Aug 14 '16 at 10:34
  • @OliverCharlesworth: Yes, and it has an OK answer by Dietmar. The first person ever to (inadvertently, I believe) call me a C++ "expert", I believe just to soften his remarks after I'd used much too harsh language in a "discussion" with Andrei over at clc++m (before I became a mod there). But, anyway, that question is itself marked as duplicate. – Cheers and hth. - Alf Aug 14 '16 at 10:44
  • Oh, and the duplicate of that has a highly upvoted decidely **incorrect** nonsense answer. :( – Cheers and hth. - Alf Aug 14 '16 at 10:45
  • @Cheersandhth.-Alf - Yup - the non-transitive duplicate has a much better answer! I would mark this as a duplicate of that, but can't now. Can you do it? – Oliver Charlesworth Aug 14 '16 at 10:54
  • I'm not sure it's a good thing to do, because if an SO mod comes along to clean up and merge answers, that will probably bring the end of the dup chain up as "solution". Which IMHO would be ungood. – Cheers and hth. - Alf Aug 14 '16 at 10:57
  • 2
    @Cheersandhth.-Alf - Sure, but posting an answer here has made the problem even worse :( (We now have n+1 "duplicates".) I've switched the direction of the duplicate "edge" between those two questions, so everything should be good to go now. – Oliver Charlesworth Aug 14 '16 at 10:59
  • Oh, you fixed that dup chain! :) How? Anyway, marking this one as dupe. – Cheers and hth. - Alf Aug 14 '16 at 12:13
  • @Cheersandhth.-Alf - Reopened the first one, marked the second one as a dupe of the first ;) – Oliver Charlesworth Aug 14 '16 at 19:24

1 Answers1

1

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.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331