I've had some second thoughts on multiple virtual destructors, esp. after reading reading http://blogs.msdn.com/b/oldnewthing/archive/2004/05/07/127826.aspx .
Suppose I have
class Base
{
public:
Base();
virtual ~Base();
private:
Logger* _logger;
};
//and
class Derived : public Base{
public:
Derived();
virtual ~Derived();
private:
Logger* _logger;
};
in the cpp files, in each destructor I am deleting the respective _logger
pointers
Base::~Base(){ //base.cpp
delete _logger;
}
Derived::~Derived(){ //derived.cpp
delete _logger;
}
will this work as I intended, without memory leaks?
First off, if you make the base class destructor virtual
, all derived classes will automatically get a virtual
destructor if you declare them as virtual
or not. This is generally true for matching signatures: if a base class has a virtual
function with the same signature as a function in a derived class, the function in the derived class is an override
and is virtual
(although in C++ 2011 you can prevent further overriding using the final
keyword in which case another override would create an error).
That said, destructors are special: when you make a destructor virtual
it will still be called even if there is another overriding destructor! The only impact of a destructor being virtual
is what happens if you delete
an object using a pointer to a base class when the object actually happens to be of a derived type: If the destructor isn't virtual
you get undefined behavior while the Right Thing happens if the destructor is virtual
. For example:
class not_a_base {};
class bad_idea: public not_a_base {};
class a_base { public: virtual ~a_base() {} };
class ok: public a_base {};
int main() {
a_base* ab = new ok;
delete ab; // <---- all is good here!
not_a_base* nab = new bad_idea;
delete nab; // <---- results in undefined behavior
}
The reason destructors are not virtual
by default is simply that this would mean that object size is always increased by a word size which is unacceptable in general.