The effect of both basic and derived virtual destructors

I had some thoughts on several virtual destructors, especially. after 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 cpp files, in each destructor I delete the corresponding _logger pointers

 Base::~Base(){ //base.cpp delete _logger; } Derived::~Derived(){ //derived.cpp delete _logger; } 

Will this work as I expected without memory leaks?

+6
source share
2 answers

First of all, if you create a virtual base class destructor, all derived classes will automatically receive a virtual destructor if you declare them virtual or not. This is usually true for signature matching: if the base class has a virtual function with the same signature as the function in the derived class, the function in the derived class is override and has the value virtual (although in C ++ 2011 you can prevent further overriding using the key final , in which case another redefinition will cause an error).

However, destructors are special: when you create a virtual destructor, it will still be called, even if there is another main deregulator! The only hit of the destructor that is virtual is what happens if you delete an object using a pointer to the base class when the object is actually of a derived type: if the destructor is not virtual , you get undefined while Right Thing happens. if the destructor is virtual . For instance:

 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 simply means that this will mean that the size of the object always increases by the size of the word, which is generally unacceptable.

+3
source

Base::_logger is another variable and then Derived::_logger . So you have to remove Derived::_logger in Derived dctor or memory leak.

Please note that this has nothing to do with being closed. Consider this sample program:

 #include <iostream> class A { public: bool foo; }; class B: public A { public: bool foo; }; int main() { B b; std::cout << &b.B::foo << ' ' << &b.A::foo << '\n'; } 

The addresses are different. This means that they are different variables, although they have the same name. This is possible because each class introduces its own namespace, so the names do not conflict. The first is A :: foo, the other is B :: foo.

Since your destructors are virtual, both are called, and the correct _logger will be deleted in both of them.

+4
source

All Articles