C++ Base Class Destructors
Introduction
In terms of the interface design in C++, sometimes it could be confusing to the developer as there can be many options such as runtime polymorphisms and different key words and specifiers such as public
, protected
, private
, and virtual
.
For the C++ base class, the rule of thumb for destructor is “A base class destructor should be either public
and virtual
, or protected
and non-virtual
”. There are also some very rare use cases when the base class destructor is protected
and virtual
.
In this blog post, I would like to discuss when and why to use public
and virtual
destructor, protected
and non-virtual
destructor, protected
and virtual
destructor for base class, and how the other combinations are eliminated.
Public and Virtual Destructor
When a base class is meant to be polymorphic at runtime, we should use public
and virtual
destructor for the base class, to ensure the base class always gets destructured correctly.
1 |
|
If the base class destructor is not public
, the base class destructor is not accessible outside the class and the code of deleting the object from a base class pointer will result in a compile-time error.
If the base class destructor is not virtual
, when the object is deleted via a base class pointer, only the base class instance will be deleted and the derived class instance, if there is any, will become a memory leak.
Protected and Non-Virtual Destructor
When a base class is not meant to be polymorphic at runtime, but its interface is still meant to be inherited, we should use protected
and non-virtual
destructor for the base class.
1 |
|
If a base class is not meant to be polymorphic at runtime, the base class is not meant to be an abstract class which has at least one virtual function to be overridden. Therefore, for performance reasons, there should be no virtual function in the base class, including the destructor. The user could still use virtual functions for the base class, including making the destructor virtual
, and the program still compiles and runs fine. But having abstract classes and virtual functions results in a vtable attached to any class instance created at runtime and these runtime polymorphism performance overhead can be large, especially when there are many of such objects being created and deleted.
The base class destructor cannot be private
. Otherwise, the base class cannot be destructed after the inherited class is destructed and it will be a compile-time error.
The base class destructor is not recommended be public
. The user could accidentally use the base class pointer to delete derived object and it is an undefined behavior.
Protected and Virtual Destructor
As I mentioned in the “Protected and Non-Virtual Destructor” previously, making the protected
destructor virtual
will not break the program but it comes with a performance cost. Therefore, usually we will not make the protected
destructor virtual
and pay unnecessary performance costs. However, there are some corner cases that we will have to make the protected
destructor virtual
and pay the performance costs.
This is an example of a simplified Component Object Model (COM) object implementation and derivation. In this case, we have to make the base class protected
destructor virtual
to make sure both the derived object and the base object are correctly destructed.
1 |
|
References
C++ Base Class Destructors