Blog Datasheets Home About me Clients My work Services Contact

G2Labs Grzegorz Grzęda

Virtual destructor in C++

May 6, 2023

You may have noticed, that every time, when an interface is being introduced, there is a virtual destructor declared.

1
2
3
4
5
struct IInterface{
	virtual ~IInterface() {}

	virtual void someMethod() = 0;
};

But actually, what for is that destructor need to be virtual?

Begin with the end in memory

When we construct our objects everything is fine. But what if:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>

struct Base{
	Base(){ std::cout << "Base Ctor" <<std::endl; }
	~Base(){ std::cout << "Base Dtor" <<std::endl; }
};

struct Deriv : Base{
	Deriv(){ std::cout << "Deriv Ctor" <<std::endl; }
	~Deriv(){ std::cout << "Deriv Dtor" <<std::endl; }
};

int main(){
	//...

	Base* d = new Deriv;

	delete d; // deleting by Base type!!!

	//...
}

We would get:

1
2
3
Base Ctor
Deriv Ctor
Base Dtor

Where is the Deriv Dtor? What if we were supposed to do something important in the destructor? Some cleanup, send a log entry? This is undefined behavior.

But, if we add that virtual to the Base::~Base() we will get the result as expexted:

1
2
3
4
Base Ctor
Deriv Ctor
Deriv Dtor
Base Dtor

Now everything is fine. So when should we make dtors virtual? Well, when compiling with -Wall flag, the compiler will suggest the answer: if at leas one method is virtual (even not purely), we should make the dtor virtual as well.


➡️ Practical examples of applying SOLID principles to real-world scenarios


⬅️ Mastering code cohesion and coupling for cleaner designs


Go back to Posts.