Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is a derived class destructor definition required if base class destructor is virtual?

I am trying the following example:

class base // base class
{
public:
    std::list<base*> values;
    base(){}
    void initialize(base *b) {
        values.push_front(b);
    }
    virtual ~base()
    {
        values.clear();
        cout<<"base called"<<endl;
    }
};

class derived : public base // derived class
{
public:
    ~derived(){
        cout<<"derived called"<<endl;
    }

};

int main()
{
    derived *d = new derived;
    base *b = new base;
    b->initialize(static_cast<base *>(d)); /* filling list */
    delete b;
    return 0;
}

Q.1) Why does destructor of derived class not get called, as in base class destructor I am performing values.clear()?

Q.2) Is derived class destructor definition required if base class destructor is virtual?

like image 355
Shashank Jain Avatar asked Dec 17 '22 01:12

Shashank Jain


2 Answers

Q1. Because you're not deleting an object of type derived. You only do delete b;, which deletes a base. You should also call delete d;.

Also, you should specify what object is responsible for memory management. Your design is prone to error. You're better off using a smart pointer to prevent ambiguity. Also, to behave as you expect it, the destructor should be:

virtual ~base()
{
    for ( int i = 0 ; i < values.size() ; i++ )
        delete values[i];
    values.clear();
    cout<<"base called"<<endl;
}

Of course, with this approach, it would be undefined behavior calling delete d; in your main.

Q2. No, the definition is not required.

like image 55
Luchian Grigore Avatar answered May 04 '23 01:05

Luchian Grigore


Why does destructor of derived class is not getting called, as in base class destructor I am performing values.clear();

values.clear() removes all the pointers from this list. It does not delete the objects being pointed to; that would be extremely dangerous, since the list has no way of knowing whether it's responsible for their lifetime, or whether they are just being used to refer to objects managed elsewhere.

If you want the list to own the objects, then you must either delete them yourself when removing them, or store smart pointers such as std::unique_ptr<base>. If your compiler doesn't support the new smart pointers, then you might find Boost's Pointer Container library useful.

Does derived class destructor definition is required. If base class destructor is virtual.

It's only needed if there is something in the derived class that needs cleaning up. There's no need to define an empty one if there's nothing for it to do.

like image 38
Mike Seymour Avatar answered May 04 '23 00:05

Mike Seymour