Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Default destructor in subclasses of base class with a virtual destructor

I have a base class A with a virtual destructor. A has descendants B and C which use the default destructor. Is it safe to delete an object of C through a pointer to A?

More specifically, consider this sample code:

class A {
 public:
      A(){};
      virtual ~A() {/* code here */};
 };
 class B: public A {
      B() {/* code....*/};
      /* NO DESTRUCTOR SPECIFIED */
   };
 class C: public B {/*same as above, no destructor */};
 class D: public B {/* same as above, no destructor*/}

The code to be run looks something like this:

A* getAPointer(void); /* a function returning a C or a D*/
A* aptr=getAPointer();
/* aptr is declared as A*, but points to either an object of class C 
  or class D*/
delete aptr;

Is the delete aptr safe? Does it do the right thing: if aptr points to an object of class C, the aptr first calls C's destructor, then B's destructor, and finally A's destructor ?

like image 908
kdog Avatar asked Jan 20 '18 12:01

kdog


People also ask

Is the default destructor virtual?

The destructor is not user-provided (meaning, it is either implicitly declared, or explicitly defined as defaulted on its first declaration) The destructor is not virtual (that is, the base class destructor is not virtual) All direct base classes have trivial destructors.

Is there a default destructor?

The default destructor calls the destructors of the base class and members of the derived class. The destructors of base classes and members are called in the reverse order of the completion of their constructor: The destructor for a class object is called before destructors for members and bases are called.

Can destructor of base class be virtual?

If your base class destructor is virtual then objects will be destructed in a order(firstly derived object then base ). If your base class destructor is NOT virtual then only base class object will get deleted(because pointer is of base class "Base *myObj"). So there will be memory leak for derived object.

In which case virtual destructor must be there in base class?

Deleting a derived class object using a pointer of base class type that has a non-virtual destructor results in undefined behavior. To correct this situation, the base class should be defined with a virtual destructor. For example, following program results in undefined behavior.


2 Answers

Is it safe to delete an object of C through a pointer to A?

Yes, it is totally safe as all the destructors in classes B, C and D will be implicitly virtual.

From:

15.4 Destructors [class.dtor]

10 A destructor can be declared virtual (13.3) or pure virtual (13.4); if any objects of that class or any derived class are created in the program, the destructor shall be defined. If a class has a base class with a virtual destructor, its destructor (whether user- or implicitly-declared) is virtual.

As A has a virtual destructor, then B, and C, D respectively, have virtual destructors and:

delete aptr;

works correctly.

like image 198
Edgar Rokjān Avatar answered Oct 18 '22 05:10

Edgar Rokjān


Yes, it's safe. Adding virtual to the destructors of your derived classes is redundant.

Consider how the mechanism works. When delete is used, the runtime needs to know with which destructor the destruction chain should begin. If the static type of the delete operand has a virtual destructor, then that's already sufficient for the runtime to know that it must take the extra trouble and inspect the dynamic type.

In your case, it finds that the dynamic type is C, so C::~C is called. C::~C automatically leads to B::~B and that one automatically leads to A::~A.

A requirement for C's (or B's) destructor to be virtual would be pointless. After all, the runtime has to find out the dynamic C type anyway if A::~A is virtual. At that point, it doesn't care whether C::~C is virtual or not. What difference would it make?

like image 35
Christian Hackl Avatar answered Oct 18 '22 04:10

Christian Hackl