TLDR: Always mark your destructors (at least for classes that may be extended) as virtual
.
As the name implies this is a combination of destructors and virtual functions.
Very important when dealing with polymorphism.
#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* base = new Base();
delete base;
std::cout << " ---------------- \n";
Derived* derived = new Derived();
delete derived;
}
// This prints
// Base Constructor
// Base Destructor
// ----------------
// Base Constructor
// Derived Constructor
// Derived Destructor
// Base Destructor
int main()
{
Base* base = new Base();
delete base;
std::cout << " ---------------- \n";
Derived* derived = new Derived();
delete derived;
std::cout << " ---------------- \n";
Base* poly = new Derived();
delete poly;
}
// This will print
// Base Constructor
// Base Destructor
// ----------------
// Base Constructor
// Derived Constructor
// Derived Destructor
// Base Destructor
// ----------------
// Base Constructor
// Derived Constructor
// Base Destructor
As you can see the Derived Destructor is not executed, and that can cause memory leak.
We just need to add the virtual
keyword in our Base
class destructor, and them the Derived
destructor will be called correctly.
class Base
{
public:
Base() { std::cout << "Base Constructor\n"; }
virtual ~Base() { std::cout << "Base Destructor\n"; }
};
// This will print
// Base Constructor
// Base Destructor
// ----------------
// Base Constructor
// Derived Constructor
// Derived Destructor
// Base Destructor
// ----------------
// Base Constructor
// Derived Constructor
// Derived Destructor
// Base Destructor