Virtual Destructors in C++


In C++, destructors are special member functions that are invoked when an object is destroyed. Virtual destructors are primarily used to ensure proper cleanup of resources in a class hierarchy involving inheritance.

When a class has a virtual destructor, the destructor of the derived class is called first, followed by the destructor of the base class. This ensures that resources allocated in derived classes are correctly released, avoiding resource leaks.

Why Use Virtual Destructors?

Consider the following example without a virtual destructor:

    #include <iostream>

    class Base {
    public:
        Base() { std::cout << "Base constructor\n"; }
        ~Base() { std::cout << "Base destructor\n"; }
    };

    class Derived : public Base {
    public:
        Derived() { std::cout << "Derived constructor\n"; }
        ~Derived() { std::cout << "Derived destructor\n"; }
    };

    int main() {
        Base* obj = new Derived();
        delete obj;
        return 0;
    }
        

Output:

    Base constructor
    Derived constructor
    Base destructor
        

In the above code, the destructor of the derived class (Derived) is never called because the destructor in the base class (Base) is not virtual. This can lead to resource leaks if the derived class manages any resources.

Using a Virtual Destructor

To fix the issue, declare the destructor of the base class as virtual:

    #include <iostream>

    class Base {
    public:
        Base() { std::cout << "Base constructor\n"; }
        virtual ~Base() { std::cout << "Base destructor\n"; }
    };

    class Derived : public Base {
    public:
        Derived() { std::cout << "Derived constructor\n"; }
        ~Derived() { std::cout << "Derived destructor\n"; }
    };

    int main() {
        Base* obj = new Derived();
        delete obj;
        return 0;
    }
        

Output:

    Base constructor
    Derived constructor
    Derived destructor
    Base destructor
        

Now, the destructor of the derived class is called first, followed by the destructor of the base class, ensuring proper cleanup.

Best Practices

Here are some best practices for using virtual destructors:

  • Declare the destructor as virtual in any base class that is intended to be inherited.
  • If the base class destructor is empty, consider making it virtual and default to indicate that no custom cleanup is needed.
  • Do not declare destructors as virtual unless the class is intended to be polymorphic (i.e., used with pointers or references).

Conclusion

Virtual destructors are a crucial concept in C++ for managing resources in polymorphic class hierarchies. By using virtual destructors, you ensure that all destructors in the hierarchy are called in the correct order, preventing resource leaks and undefined behavior.





Advertisement