Problem with virtual functions called from a destructor

J

Juha Nieminen

This is a simplified version of the situation (the actual situation
is quite more complex, but when stripped to the bare minimum, it's
like this):

class BaseClass
{
public:
virtual void cleanup();
virtual ~BaseClass() { cleanup(); }
};

The cleanup() function is not only called when destroying the object
but also at other times during the lifetime of the object, and it's
usually called through a BaseClass pointer and sometimes implemented
in a derived class.

Naturally the problem is that the BaseClass destructor will not call
the implementation of cleanup() in the derived class, only its own.
This is a bummer, but I suppose it's like it should be (because,
basically, the derived part of the object "doesn't exist" anymore
when the destructor of the base class is executed).
The only clean solution to this is to explicitly call cleanup() in
the destructor of the derived class too.

Isn't there any way of automatically making the destructor of the
derived class call its own cleanup() function without having to write
it explicitly? The problem is that this is very easy to forget, it
obviously doesn't cause any compiler errors nor warnings and the
resulting behavior of the program can be quite confusing.
 
L

liud0616

This is a simplified version of the situation (the actual situation
is quite more complex, but when stripped to the bare minimum, it's
like this):

class BaseClass
{
public:
virtual void cleanup();
virtual ~BaseClass() { cleanup(); }

};

The cleanup() function is not only called when destroying the object
but also at other times during the lifetime of the object, and it's
usually called through a BaseClass pointer and sometimes implemented
in a derived class.

Naturally the problem is that the BaseClass destructor will not call
the implementation of cleanup() in the derived class, only its own.
This is a bummer, but I suppose it's like it should be (because,
basically, the derived part of the object "doesn't exist" anymore
when the destructor of the base class is executed).
The only clean solution to this is to explicitly call cleanup() in
the destructor of the derived class too.

Isn't there any way of automatically making the destructor of the
derived class call its own cleanup() function without having to write
it explicitly? The problem is that this is very easy to forget, it
obviously doesn't cause any compiler errors nor warnings and the
resulting behavior of the program can be quite confusing.
 
T

terminator

This is a simplified version of the situation (the actual situation
is quite more complex, but when stripped to the bare minimum, it's
like this):

class BaseClass
{
public:
virtual void cleanup();
virtual ~BaseClass() { cleanup(); }

};

The cleanup() function is not only called when destroying the object
but also at other times during the lifetime of the object, and it's
usually called through a BaseClass pointer and sometimes implemented
in a derived class.

Naturally the problem is that the BaseClass destructor will not call
the implementation of cleanup() in the derived class, only its own.
This is a bummer, but I suppose it's like it should be (because,
basically, the derived part of the object "doesn't exist" anymore
when the destructor of the base class is executed).
The only clean solution to this is to explicitly call cleanup() in
the destructor of the derived class too.

Isn't there any way of automatically making the destructor of the
derived class call its own cleanup() function without having to write
it explicitly? The problem is that this is very easy to forget, it
obviously doesn't cause any compiler errors nor warnings and the
resulting behavior of the program can be quite confusing.

you can invent a techniqe but it can not become implicit.
a popular way is this:

class baseClass{
protected:
bool clean_flag;
virtual void do_clean();
public:
baseClass():clean_flag(false){};
bool cleanup(){//return true unless cleaned before;
if(clean_flag) return false;
do_clean();
return clean_flag=true;//set flag ,return done(true)!
};
void do_sth(){
//do some dirty thing:
...
clean_flag=false;//reset flag
};
virtual ~baseClass(){cleanup()};
};

and you need overload 'do_clean' as well as the destructor in
subclasses:

class derivedClass:
public baseClass
{protected:
virtual void do_clean();
public:
virtual ~derivedClass(){cleanup()};
};
 
T

terminator

class baseClass{
protected:
bool clean_flag;
virtual void do_clean();
public:
baseClass():clean_flag(false){};
bool cleanup(){//return true unless cleaned before;
if(clean_flag) return false;
do_clean();
return clean_flag=true;//set flag ,return done(true)!
};
void do_sth(){
//do some dirty thing:
...
clean_flag=false;//reset flag
};
virtual ~baseClass(){cleanup()};

};
sorry,this one is better:
class baseClass{
private:
bool clean_flag;
//LOOK HERE:
bool set_clean(){
if (is_clean()) return false;
return clean_flage=true;
};
protected:
//LOOk,I AM HERE:
bool reset_clean(){
if(!is_clean()) return false;
clean_flage=false;
return true;
};
virtual void do_clean();
public:
baseClass():clean_flag(false){};
//WATCH THIS:
bool is_clean(){return clean_flage;};
bool cleanup(){//return true unless cleaned before;
if(is_clean()) return false;
do_clean();
return set_clean();//set flag ,return done(true)!
};
void do_sth(){
//do some dirty thing:
...
//LOOK @ ME
reset_clean();//reset flag
};
virtual ~baseClass(){cleanup()};
};

regards,
FM.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,962
Messages
2,570,134
Members
46,690
Latest member
MacGyver

Latest Threads

Top