Click here to Skip to main content
15,892,161 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
Hi
I have a class Derived which implements an interface Base, something like this
C++
class Base {
public:
    virtual void foo () = 0;
};

class Derived : public Base {
public:
    Derived (int i = 5) {
        data = new double [i];
    }
    ~Derived () {
        foo ();
    }
    void foo () {
        if (data) {
            delete []data;
        }
    }
private:
    double *data; // an array
};

The foo here as you can see does the cleaning up routine. Now I create an instance of class Derived and store it to variable of type Base:
C++
int n;
Base *base;
n = 1024 * 1024 * 8; // some random big number
base = new Derived (n);
delete base;

After this, the used resources still not reclaimed, although the variable base is already invalid. I notice that It doesn't even go to the destructor of ~Derived() hence the resources is still there. I don't know why, maybe someone can explain this.

After a little while I come up with a solution:
C++
int n;
Base *base;
n = 1024 * 1024 * 8;
base = new Derived (n);

Derived *p;
p = dynamic_cast<Derived*>(base);
if (p) {
    delete p;
}

Are there any other solution than this?
Posted
Comments
Sergey Alexandrovich Kryukov 21-Sep-12 17:46pm    
Pretty good simple question, clearly formulated. (Unfortunately, this is so rare these days.) I voted 4 (not 5 because you still miss something :-).
Please see my solution.
Good luck,
--SA
pasztorpisti 21-Sep-12 18:25pm    
Roboust well designed code shouldn't employ dynamic_cast. dynamic_cast usually means you made a bad design decision somewhere. I use it rarely and even in that case only as a temporary hack to spare time for something else that is urgent.
momond19 21-Sep-12 20:02pm    
yea I completely agree with you, that is why I ask for another solution :D
pasztorpisti 21-Sep-12 20:16pm    
The fact that you found out that this kind of delete results in bug already presumes some know-how on your side. :-D
Sergey Alexandrovich Kryukov 21-Sep-12 21:13pm    
What do you mean? "I know how to make a subtle bug which leaves the code looking innocent"? :-)
--SA

1 solution

Your solution would work, but it is artificial and bad for maintenance. Don't do such things.

Instead, add a virtual destructor Base::~Base.

In this case, the destructor Derived::~Derived will be called even if your compile-time type you use in delete is Base. Based on this compile-time class, the call to the destructor Base::~Base will be dispatched to Derived::~Derived through late binding first, and then, because of the mechanism of automatic call base class destructor, Base::~Base will be called.

Try it: I tested this code before posting the answer.

[EDIT]

And fix one minor flaw: make the function foo private.

—SA
 
Share this answer
 
v4
Comments
Espen Harlinn 21-Sep-12 19:44pm    
Right :-D
Sergey Alexandrovich Kryukov 21-Sep-12 19:48pm    
Thank you, Espen.
--SA
momond19 21-Sep-12 20:10pm    
Nice so simple!
It works with ~Base () {}.
Thanks SA

Btw if I try to declare the destructor as pure virtual function virtual ~Base() = 0; It doesn't work, it still asking for the implementation at linking.
Sergey Alexandrovich Kryukov 21-Sep-12 20:33pm    
You are welcome.

Pure virtual does not work just because implementation requires all the base class destructors to be called. You can keep it pseudo-abstract if you want, which means, with empty { } block... You can also make a non-virtual (but could be also virtual) destructor only in the base which calls some virtual clean-up method. That method could be pure virtual. And then you can override it to make the class non-abstract.

By the way, look at C++/11 version with explicit overrides and final:
http://en.wikipedia.org/wiki/C%2B%2B11#Explicit_overrides_and_final

This is an attempt to modernize C++ (just a bit) by using ideas practiced in more advanced OOP implementations for a long time already (C#, Object or Delphi Pascal, Java...). It prevents a number of similar mistakes.

Good luck, call again.
--SA
Espen Harlinn 22-Sep-12 4:29am    
"which calls some virtual clean-up method" - will probably not work as expected, have a look at:
http://www.artima.com/cppsource/nevercall.html

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900