Friday, April 4, 2014

Destructor in base class needed to be virtual in C++

Problem

Why does a destructor in base class need to be declared virtual?
Follow up - Is it always required for base class to have virtual destructors?

Solution

You want them to be virtual so that all subclass destructors are automatically called when the object is destroyed, even if it is destroyed through a pointer to the base class.

Calling a method with an object pointer always invokes:
  • the most derived class function, if a method is virtual.
  • the function implementation corresponding to the object pointer type (used to call the method), if a method is non-virtual.
A virtual destructor works in the same way. A destructor gets called when an object goes out of scope or when we call delete on an object pointer.

When any derived class object goes out of scope, the destructor of that derived class gets called first. It then calls its parent class destructor so memory allocated to the object is properly released.
But, if we call delete on a base pointer which points to a derived class object, the base class destructor gets called first (for non-virtual function). For example:
class Base {
public:
    Base() { cout << "Base Constructor " << endl; }
    ~Base() { cout << "Base Destructor " << endl; } /* see below */
};
 
class Derived: public Base {
public:
    Derived() { cout << "Derived Constructor " << endl; }
    ~Derived() { cout << "Derived Destructor " << endl; }
};
 
void main() {
    Base *p = new Derived();
    delete p;
}

Output
Base Constructor
Derived Constructor
Base Destructor

If we declare the base class destructor as virtual, this makes all the derived class destructors virtual as well. If we replace the above destructor with:
virtual ~Base() {
    cout << "Base Destructor" << endl;
}

Then the output becomes:
Base Constructor
Derived Constructor
Derived Destructor
Base Destructor

So we should use virtual destructors if we call delete on a base class pointer which points to a derived class.

Follow up question - Is it always required for base class to have virtual destructor. Answer is no.
As described by Johannes here, applying virtual to base class would make it impossible to apply the empty base class optimization, and could multiply the size of classes up to 16 times than what it would be without virtual on common platforms.

A virtual destructor is needed when you delete an object whose dynamic type is DerivedClass by a pointer that has type BaseClass*. The virtual makes the compiler associate information in the object making it able to execute the derived class constructor. Missing the virtual in such cases causes undefined behavior.

If you don't need this, and your class is only used as a base class, it's best to make the destructor protected, thus preventing that users accidentally delete in the described way.  For more clarity see Virtuality, specifically, "Guideline #4: A base class destructor should be either public and virtual, or protected and nonvirtual."

References
http://tianrunhe.wordpress.com/2012/04/13/destructor-in-base-class-needed-to-be-virtual-in-c/
http://stackoverflow.com/questions/5873515/why-should-the-destructor-of-base-classes-be-virtual
 

0 comments:

Post a Comment