[comp.lang.c++] Calling virtuals from destructors

stuart@NECAM.tdd.sj.nec.com (Stuart Palmer) (01/08/91)

If you call a virtual member function from a destructor, what is
the behavior?  We ran some tests and found differences between
Glockenspiel 1.2 and Sun 2.0 compilers.

In Sun 2.0, if you call a virtual member function from
a destructor, the "actual" virtual function that is compiled into
the class vtbl will not get called.  Rather, the virtual function
at the class level where the call was made gets called.  If this is
confusing, see the code sample below.

This is different than Glockenspiel 1.2.  1.2 calls the virtual
function from the vtbl (as might be expected?).

Is this a bug in one of the compilers?  I looked throught the Turbo
C++ bug list and found a similar bug concerning virtual functions
called from member functions.  I would appreciate someone 
describing the Correct (tm) behavior to me.

Thanks!


**********************************Code example********************************

class Base {
  public:
   Base();
   virtual ~Base();
   virtual void some_func();
}
Base::Base(){}
Base::~Base(){ some_func(); }
void Base::some_func(){ printf ("Base called.\n"); }

class Derived : public Base {
  public:
   Derived();
   ~Derived();
   void some_func();
}
Derived::Derived(){}
Derived::~Derived(){ }
void Derived::some_func(){ printf ("Derived called.\n"); }

main() { 
   Derived d;
}


**********************************Output**************************************

1.2 output:
Derived called.

2.0 output:
Base called.

******************************************************************************




--
Stuart Palmer                    stuart@tdd.sj.nec.com
NEC America, Inc.
110 Rio Robles
San Jose, CA 95134

jak@cs.brown.edu (Jak Kirman) (01/09/91)

In article <424@nec-gw.nec.com> stuart@NECAM.tdd.sj.nec.com (Stuart Palmer) writes:
-  If you call a virtual member function from a destructor, what is
-  the behavior?  We ran some tests and found differences between
-  Glockenspiel 1.2 and Sun 2.0 compilers.
-
-  In Sun 2.0, if you call a virtual member function from
-  a destructor, the "actual" virtual function that is compiled into
-  the class vtbl will not get called.  Rather, the virtual function
-  at the class level where the call was made gets called.  If this is
-  confusing, see the code sample below.
-
-  This is different than Glockenspiel 1.2.  1.2 calls the virtual
-  function from the vtbl (as might be expected?).
-
-  Is this a bug in one of the compilers?  I looked throught the Turbo
-  C++ bug list and found a similar bug concerning virtual functions
-  called from member functions.  I would appreciate someone 
-  describing the Correct (tm) behavior to me.
-
-  Thanks!
-
-  **********************************Code example********************************
-
-  class Base {
-    public:
-  >  Base();
-  >  virtual ~Base();
-  >  virtual void some_func();
-  }
-  Base::Base(){}
-  Base::~Base(){ some_func(); }
-  void Base::some_func(){ printf ("Base called.\n"); }
-
-  class Derived : public Base {
-    public:
-  >  Derived();
-  >  ~Derived();
-  >  void some_func();
-  }
-  Derived::Derived(){}
-  Derived::~Derived(){ }
-  void Derived::some_func(){ printf ("Derived called.\n"); }
-
-  main() { 
-  >  Derived d;
-  }

From Ellis & Stroustrup ARM 12.7 Constructors and destructors

    Member functions may be called in constructors and destructors.
    This implies that virtual functions may be called (directly or
    indirectly).  The function called will be the one defined in the
    constructor's (or destructor's) own class or its bases, but not any
    function overriding it in a derived class.  This ensures that
    unconstructed objects will not be accessed during construction or
    destruction.

The problem is that the some_func defined in Derived may access data
belonging to the Derived object which is destroyed by the Derived
destructor.  Since the Derived destructor is called before the Base
destructor, it would be unsafe to call functions which might operate on
that data.  The behaviour of Sun's compiler is correct.

                                Jak                            jak@cs.brown.edu
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Tell me what company thou keepest, and I'll tell thee what thou art.
                                                               -- Cervantes

sarima@tdatirv.UUCP (Stanley Friesen) (01/15/91)

In article <424@nec-gw.nec.com> stuart@NECAM.tdd.sj.nec.com (Stuart Palmer) writes:
>
>If you call a virtual member function from a destructor, what is
>the behavior?
 
>In Sun 2.0, if you call a virtual member function from
>a destructor, the "actual" virtual function that is compiled into
>the class vtbl will not get called.  Rather, the virtual function
>at the class level where the call was made gets called.

This is correct, at least for version 2.XC++.
This is so because by the time a destructor is called all derived classes
have been destroyed, so the object is no longer a derived class object.
Thus the destuctor can make a 'static' call to the function.


>This is different than Glockenspiel 1.2.  1.2 calls the virtual
>function from the vtbl (as might be expected?).

This is (or would be) wrong for a 2.X compiler, but it may be that as a 1.2
compiler this was correct at the time.  (I.e. this could be something that
changed between version 1.2 and 2.0 of cfront).

>Is this a bug in one of the compilers?

It is either a bug or an archaism in the Glockenspiel compiler.


By the way, this should probably be in the FAQ, it has been asked enough.
-- 
---------------
uunet!tdatirv!sarima				(Stanley Friesen)