I understand that derived class is type compatible with a pointer to its base class. In the given sample code, new bar object construction takes place calling foo::foo() followed by bar::bar(). In the respective constructors, I am allocating resources to class members foo::int *a and bar::int *b.
Now I am initializing thus constructed object to base class type. With obj, I can call the base class destructor but not the derived class destructor. So, how can I deallocate the derived class resources in this case? Is this not a memory leak ?
#include <iostream>
class foo
{
int *a;
public:
foo()
{
a = new int[5];
std::cout << "\n foo constructor" << std::endl;
}
~foo()
{
std::cout << "\n foo destructor" << std::endl;
delete[] a;
}
};
class bar : public foo
{
int *b;
public:
bar()
{
b = new int[5];
std::cout << "\n bar constructor" << std::endl;
}
~bar()
{
std::cout << "\n bar destructor" << std::endl;
delete[] b;
}
};
int main()
{
foo *obj = new bar; // Derived class object is type compatible with base class
delete obj; // Equivalent to obj->~foo();
return 0;
}
Thanks.
This is where the idea of the “virtual destructor” comes in. Technically speaking, if you delete an object through a pointer of a base class type, you must mark that base class destructor virtual or the result is undefined. If you do mark the destructor virtual, the meaning is different from other virtual functions. Instead of meaning “derived classes override this behavior,” it means “when deleting this object through a base class pointer, call the derived destructors before calling the base constructor.” This is the behavior you want.
As a general rule, any class you define that you plan on subclassing should have a virtual destructor to prevent this sort of problem.