Why is base-class destructor called on derived object when destructor of derived class is non-virtual?
Asked Answered
T

3

6

Why are all destructors, ~D(),~C(),~B(),~A() being called in the example below?

There is only one virtual destructor: that of A.

Here is the code:

#include<iostream>
using namespace std;

class A
{
public:
  virtual ~A()
  {
    cout<<"destruct A\n";
  }

};
class B:public A
{
public:
  ~B()
  {
  cout<<"destruct B\n"; 
  }
};
class C:public B
{
public:
  ~C()
  {
    cout<<"destruct C\n";
  }
};
class D:public C
{
public:
   ~D()
   {
     cout<<"destruct D\n"; 
   }
};

int main()
{
    A* ptr = new D();
    delete ptr;
    return 0;
}
Terryl answered 17/10, 2012 at 5:31 Comment(1)
Because that is what the rules of the language say should happen.Carminacarminative
C
6

Once A's destructor is declared virtual, the destructors of all derived classes are also virtual, even if they aren't explicitly declared as such.. So the behaviour you see is exactly what is expected

Carminacarminative answered 17/10, 2012 at 5:33 Comment(1)
@Subconscious a D is accessed via a pointer to A, which is what the delete is called on. If A's destructor weren't virtual, only ~A() would be called. You can easily check for yourself.Carminacarminative
B
7

The destruction order in derived objects goes in exactly the reverse order of construction: first the destructors of the most derived classes are called and then the destructor of the base classes.

A destructor can be defined as virtual or even pure virtual. You would use a virtual destructor if you ever expect a derived class to be destroyed through a pointer to the base class. This will ensure that the destructor of the most derived classes will get called:

A* b1 = new B;//if A has a virtual destructor
delete b1;//invokes B's destructor and then A's

A* b1 = new B;//if A has no virtual destructor
    delete b1;//invokes A's destructor ONLY

If A does not have a virtual destructor, deleting b1 through a pointer of type A will merely invoke A's destructor. To enforce the calling of B's destructor in this case we must have specified A's destructor as virtual:

virtual ~A();

REFERENCE

Bogan answered 17/10, 2012 at 5:45 Comment(1)
"even pure virtual" - when to prevent run time errors you have to create body for pure virtual destructor in order to allocate address in virtual table for that destructor, not just nullptrSubconscious
C
6

Once A's destructor is declared virtual, the destructors of all derived classes are also virtual, even if they aren't explicitly declared as such.. So the behaviour you see is exactly what is expected

Carminacarminative answered 17/10, 2012 at 5:33 Comment(1)
@Subconscious a D is accessed via a pointer to A, which is what the delete is called on. If A's destructor weren't virtual, only ~A() would be called. You can easily check for yourself.Carminacarminative
K
0

As @juanchopanza said - declaring the base destructor virtual means all descendants have virtual destructors. This inherited virtuality is the same for any methods, not just destructors.

It's why I have interviewed people who didn't know what the keyword did because they had only ever had to override methods derived from a framework, so they were all virtual (sigh).

Kaleena answered 8/11, 2015 at 13:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.