In C++, a pure virtual destructor is a special destructor used to declare a class as abstract and to ensure that derived classes correctly call the base class's destructor. It must be declared in the base class and must have an implementation, even though it is declared as pure virtual (= 0).
Why Use Pure Virtual Destructors?
Pure virtual destructors are primarily used for the following two purposes:
-
Define Abstract Classes: By declaring at least one pure virtual function, a class is defined as abstract. This means such a class cannot be directly instantiated and is primarily used as a base class. A pure virtual destructor is one way to achieve this.
-
Ensure Derived Classes Correctly Call the Base Class's Destructor: In polymorphic scenarios, the base class destructor should be declared as virtual to ensure that when a derived class object is deleted through a base class pointer, the derived class's destructor is correctly called. Declaring the destructor as pure virtual also ensures that the base class itself is not instantiated while providing the correct destructor behavior.
Example
Suppose there is an abstract base class Shape whose purpose is to define an interface for various concrete shape classes to implement, such as Circle and Rectangle. Here, we want to ensure that Shape cannot be directly instantiated and that the derived classes' destructors are correctly called:
cppclass Shape { public: Shape() { // Constructor code } // Pure virtual destructor virtual ~Shape() = 0; }; // Implementation of the pure virtual destructor Shape::~Shape() { // Actual destructor code, possibly for resource cleanup } class Circle : public Shape { public: Circle() { // Constructor code } ~Circle() override { // Circle-specific resource cleanup } }; class Rectangle : public Shape { public: Rectangle() { // Constructor code } ~Rectangle() override { // Rectangle-specific resource cleanup } };
In this example, although the destructor of Shape is declared as pure virtual, we still provide its implementation. This is because when objects of derived classes Circle or Rectangle are destroyed, the derived class's destructor is called first, followed by the base class Shape's destructor. If the base class destructor is not implemented, linking will fail.
Conclusion
By using pure virtual destructors, we can explicitly identify a class as abstract and ensure that when using its polymorphic features, objects are safely and correctly destroyed. This is a very important aspect of object-oriented design, especially when dealing with resource management and memory allocation.