Is there some way to call virtual function in Destructor?

Is there some way to call virtual function in Destructor?

Post by yux » Tue, 15 Jun 2004 17:18:44


Hi, I wrote this Program.

class CBase
{
public:
virtual ~CBase(){ F(); }
virtual void Do(){ cout << "CBase" << endl; }

virtual void F(){ cout << typeid(*this).name() << endl; }
};

class CDerived : public CBase
{
public:
virtual void Do(){ cout << "CDerived" << endl; }
};

void Main()
{
CDerived d;

d.F(); /// "CDerived" printed
/// "CBase" when d is destroyed
}

Now I wanna get "CDerived" when d is destroyed, how can I do?
I don't want to rewrite F() in CDerived::~CDerived(), so is there another
way I can do?
 
 
 

Is there some way to call virtual function in Destructor?

Post by Martin Sei » Tue, 15 Jun 2004 20:52:23

The behaviour of the program is fully compliant to the Standard (look
section 12.7). If the base class constructor of a derived class is called,
all data of the derived class has already been destroyed, so it would be
dangerous if a function of the derived class would be called, and therefor
the standard requires that the function declared in the base class is
called.

Regards
Martin Seiringer

"yux" wrote

 
 
 

Is there some way to call virtual function in Destructor?

Post by Michi-Schl » Fri, 18 Jun 2004 07:13:14


This should be clear:


But why is this?





So, when the CBase object's destructor is invoked, F gets called. At
that time, there is no CDerived object any more - its destruction is
already complete.

Please remember the destruction sequence in class hierarchies. When
you write

{
CDerived d;
}

at the end of the lifetime of d the following happens:

1. The dtor of CDerived is called from the system. (Even if you do not
specify a dtor, it is there, but empty)

2. The code in the dtor executes. Since you do not specify a dtor in
CDerived, the system adds one, which is empty, and nothing visible
happens here. Behind the scenes, the vtbl is modified as if the
CDerived never existed.

3. The dtors of the data members in CDerived run. Since you do not
have any data members, nothing happens.

4. The dtors of the base classes run. Since you have only one base
class, CBase, its dtor is executed, which calls F. The object now
(more precise: its vtbl) is in a state as if the derived classes never
had existed. Hence, the call of the virtual function F cannot dispatch
to CDerived::F, but must resolve to CBase::F.

-- and that's it.

Please note that

- in the dtor of a base class, all derived parts simply do not exist
any more.

- a similar sequence runs when a CDerived is constructed: In the ctor
of CBase, the CDerived is not yet there: also here F would resolve to
CBase::F.

This all leads to the conclusion that the behavior of virtual
functions called in ctors or dtors is well defined, but of not much
use, and therefore should best be avoided.

------------------------------------------------
Martin Aupperle
Die Kunst der Programmierung mit C++
ISBN ISBN 3-528-15481-0
Vieweg-Verlag
www.PrimaProgramm.de
------------------------------------------------