Calling virtual functions from destructors?

H

Henrik Goldman

Hi

I've had a problem with gcc mac osx which I think I figured out. I would
like to double check with people here to see if my understanding is correct:

I have a class A which class B inherit from. A has a pure virtual function
virtual in f1() = 0. In B I implement this function and the compiler works
out the code. However from A's destructor B can be compiled and then the
runtime aborts with saying that a call to a pure virtual function is not
allowed.

I'm assuming that B's destructor has been called before A's destructor and
thus it won't allow me to call the virtual function through the destructor.

The big question is what to do about this then? E.g. I have a class specific
cleanup method which is implemented with a GoF template pattern.

Thanks.

-- Henrik
 
R

Rolf Magnus

Henrik said:
Hi

I've had a problem with gcc mac osx which I think I figured out. I would
like to double check with people here to see if my understanding is
correct:

I have a class A which class B inherit from. A has a pure virtual function
virtual in f1() = 0. In B I implement this function and the compiler works
out the code. However from A's destructor B can be compiled and then the
runtime aborts with saying that a call to a pure virtual function is not
allowed.

I'm assuming that B's destructor has been called before A's destructor and
thus it won't allow me to call the virtual function through the
destructor.

More precisely, when the object is destroyed, B's destructor is called
first. After that finished, the object is not a B anymore. It's only an A
now. Since you don't have an implementation for f1() in A, you get into
trouble when trying to call it.
The big question is what to do about this then?

Depends on what you want to do.
E.g. I have a class specific cleanup method which is implemented with a
GoF template pattern.

Why?
 
O

ondra.holub

There is no need to make CLeanUp method virtual. Make all your clean-up
routines in destructor. If you need to make it in separate method, just
write CleanUp method for every class and call it from destructor as in
example below:

#include <iostream>

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

virtual void VMethod() = 0;

private:
void CleanUp();
};

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

virtual void VMethod()
{
}

private:
void CleanUp();
};

void A::CleanUp()
{
std::cout << "A::CleanUp()\n";
}

void B::CleanUp()
{
std::cout << "B::CleanUp()\n";
}

int main()
{
A* instance = new B();
delete instance;
}
 
D

David Harmon

On Sun, 19 Nov 2006 15:13:46 +0100 in comp.lang.c++, "Henrik Goldman"
I'm assuming that B's destructor has been called before A's destructor and
thus it won't allow me to call the virtual function through the destructor.

Yes. It is the same during construction.

This issue is covered in Marshall Cline's C++ FAQ. See the topic
"[23.5] When my base class's constructor calls a virtual function on its
this object, why doesn't my derived class's override of that virtual
function get invoked?" and "[23.7] I'm getting the same mess with
destructors: calling a virtual on my this object from my base class's
destructor ends up ignoring the override in the derived class; what's
going on?". It is always good to check the FAQ before posting.
You can read the FAQ at: http://www.parashift.com/c++-faq-lite/
The big question is what to do about this then? E.g. I have a class specific
cleanup method which is implemented with a GoF template pattern.

B's destructor should ordinarily take care of B-specific stuff.
If that's not enough, you need to be specific about what you are doing.
See also FAQ [23.6]
 
H

Henrik Goldman

More precisely, when the object is destroyed, B's destructor is called
first. After that finished, the object is not a B anymore. It's only an A
now. Since you don't have an implementation for f1() in A, you get into
trouble when trying to call it.

Correct. It took me a little while to realise this but yes it's right.

My intention is to create a class which uses RAII idiom. Upon destruction it
may need a algorithm specific way for destruction.

It's a class for handled spawning and closed processes. It is platform
independent and support several platforms. However on some unix platforms I
get weird results from fork/child and when I need to shut things down
politely I am sometimes closing the wrong pid. It's a platform specific
problem. However I have an application specific method which is 100%
fool-proof by getting the pid from a special pid file. Therefore I wanted
to create an inherited class to deal with my application specific algorithm.
However this technique backfired on me since I cannot obtain the algorithms
specific information at destruction time.
The only alternative I see is to call the destruction explicitly before
destruction time... but then RAII is pointless in this case.

-- Henrik
 
G

Greg

Henrik said:
Correct. It took me a little while to realise this but yes it's right.


My intention is to create a class which uses RAII idiom. Upon destruction it
may need a algorithm specific way for destruction.

It's a class for handled spawning and closed processes. It is platform
independent and support several platforms. However on some unix platforms I
get weird results from fork/child and when I need to shut things down
politely I am sometimes closing the wrong pid. It's a platform specific
problem. However I have an application specific method which is 100%
fool-proof by getting the pid from a special pid file. Therefore I wanted
to create an inherited class to deal with my application specific algorithm.
However this technique backfired on me since I cannot obtain the algorithms
specific information at destruction time.
The only alternative I see is to call the destruction explicitly before
destruction time... but then RAII is pointless in this case.

The code that currently calls the virtual method has simply been placed
in the wrong destructor. Moving the cleanup call to the destructor of
the derived class that needs to be cleaned up - would produce the
desired result by calling the right clean-up method at the right time.

Greg
 
T

terminator

Henrik Goldman äæÔÊå ÇÓÊ:
Correct. It took me a little while to realise this but yes it's right.


My intention is to create a class which uses RAII idiom. Upon destruction it
may need a algorithm specific way for destruction.

It's a class for handled spawning and closed processes. It is platform
independent and support several platforms. However on some unix platforms I
get weird results from fork/child and when I need to shut things down
politely I am sometimes closing the wrong pid. It's a platform specific
problem. However I have an application specific method which is 100%
fool-proof by getting the pid from a special pid file. Therefore I wanted
to create an inherited class to deal with my application specific algorithm.
However this technique backfired on me since I cannot obtain the algorithms
specific information at destruction time.
The only alternative I see is to call the destruction explicitly before
destruction time... but then RAII is pointless in this case.

-- Henrik
how about a pure virtual destructor overridden in a subclass?
 

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,777
Messages
2,569,604
Members
45,214
Latest member
JFrancisDavis

Latest Threads

Top