Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling virtual method from destructor - workaround?

I need to declare finalizing method finalize() for all descendants of the base class Base, that should be called during destruction, and my intent was to call pure virtual void Base::finalize() = 0 from the ~Base(), but c++ forbids such a thing. So my question is

How can we oblige descendants to do some finalizing work in right and preliminary defined way?

That code cannot be compiled:

#include <QDebug>
class Base {
        public:
            Base(){}
            virtual ~Base(){
                qDebug("deleting b");
                finalize();
            }
            virtual void finalize() = 0;

    };

class A : public Base
    {
    public:
        A(){}
        ~A(){}
        void finalize(){qDebug("called finalize in a");}
    };

    int main(int argc, char *argv[])
    {
        Base *b = new A;
        delete b;
    }

If I make Base::finalize() not pure virtual, it is called from ~Base() without dispatching to child since it have been already destructed.

I can call finalize() from child's destructor but question is how to force to do that. In other words my question is: is it possible to oblige people who will write descendants of the Base class to use finalizing method, well, in another way than commenting it in a documentation? :)

like image 468
Dmitriy Kachko Avatar asked Feb 02 '12 15:02

Dmitriy Kachko


3 Answers

Destructors are the right place to release acquired resources, but each class is responsible to release its own resources. Resources acquired by class A should not (and just can not) be released by class Base.

Defining virtual destructors allows class A's destructor to be called when deleting a pointer to class Base pointing to a class A object

Base* p = new A;
delete p; // Both A and Base destructors are sequencially called! 

So to achieve proper resource release you just have to release each class' resources in its own destructor.

like image 171
Antonio Pérez Avatar answered Nov 15 '22 09:11

Antonio Pérez


That's what a virtual destructor is for:

class A
{
public:
   virtual ~A() {}
};

class B : public A
{
public:
   virtual ~B() {}
};

When an object of type B is destroyed, regardless of whether from a pointer to a B or a pointer to an A, both destructors will be called. First, B::~B() and then A::~A().

like image 3
Luchian Grigore Avatar answered Nov 15 '22 08:11

Luchian Grigore


Make the base class destructor pure virtual with a body, which should do exactly what you want.

like image 2
Mark B Avatar answered Nov 15 '22 08:11

Mark B