Deleting a derived object through a base class pointer can silently cause memory leaks in C++.
Yes — even if your program runs without errors.
Let’s understand why this happens and how virtual destructors fix it.
If you ever worked with inheritance in C++, you might have used the upcasting. If not don't worry, we will discuss this.
What is Upcasting?
Pointing to a derived (child) object using a base class pointer. It’s a powerful feature of polymorphism.
// this is upcasting
BaseClass* b = new ChildClass()
However, if the base class destructor is not declared as virtual, deleting the object through a base class pointer can cause a memory leak — especially if the derived class allocates memory on the heap.
The Problem
When we delete an object using a base class pointer, C++ decides which destructor to call based on the pointer type — not the actual object type.
This behavior is called static binding.
Example Without Virtual Destructor
#include <iostream>
using namespace std;
class Base {
public:
Base() { cout << "Base Constructor\n"; }
~Base() { cout << "Base Destructor\n"; }
};
class Derived : public Base {
int* data;
public:
Derived() {
cout << "Derived Constructor\n";
data = new int[100]; // Memory allocated on heap
}
~Derived() {
cout << "Derived Destructor (Memory freed!)\n";
delete[] data;
}
};
int main() {
cout << "--- Creating Object ---\n";
Base* ptr = new Derived(); // Upcasting
cout << "\n--- Deleting Object ---\n";
delete ptr;
return 0;
}
Output
What happens here?
- Only the
Basedestructor is called - The
Deriveddestructor is not called - The dynamically allocated memory (
data) is never freed
This leads to a memory leak.
Fix: Using Virtual Destructor
class Base {
public:
Base() { cout << "Base Constructor\n"; }
virtual ~Base() { cout << "Base Destructor\n"; }
};
/*Rest of the code same...*/
Output
What happens now?
- The
Deriveddestructor is called first - Then the
Basedestructor is called - Memory allocated in the derived class is properly freed
By using virtual, we tell the compiler to determine the correct destructor at runtime based on the actual object type.
This is called dynamic binding.
Final Takeaway
If you delete objects using base class pointers, a virtual destructor is not optional — it is essential.
Ignoring this can lead to subtle memory leaks that are hard to detect in large applications.
Happy Coding!


Top comments (0)