Topic: Virtual functions and destructors: MSVC 2.2 errors


Author: lwest@ix.netcom.com (Larry West)
Date: 1995/11/14
Raw View
hf@colibri.de (Harald Fuchs) wrote in comp.std.c++:
> > struct Base1 { virtual ~Base1() {}; }
> > struct Base2 {         ~Base2() {}; }
> > struct Derived : public Base1, public Base2 { ... };

>~Derived is virtual with respect to Base1, but AFAIK not with respect
>to Base2.  If you delete a Derived* through a Base2*, all compilers I
>know only call ~Base2 ().

This seemed correct to me, but I wanted to check, so I compiled a sample
program [see below] under Borland C++ (16-bit EasyWin and 32-bit console
app) on Windows 95, MSVC++ 2.2 (32-bit console app) on Windows NT, and
MSVC++ 1.52 (16-bit DOS app).   Borland and MSVC++ 1.52 performed as you'd
expect [here's the output]:

 pB1w==pDw: ~Derived ~Base2 ~Base1
 pB2x==pDx: ~Base2
 pDDy==pDy: ~Derived ~Base2 ~Base1
 pDz as is: ~Derived ~Base2 ~Base1

Meaning that deleting Derived through a pointer of type Base2 (with
non-virtual dtor) does in fact only call Base2, since there is in principle
no information knowable to the compiler that there may be more to the
object than just Base2.

But the news is that MSVC++ 2.2 version (a console application run on both
NT and 95) faulted on the second delete (heap error), through the base
class which has a non-virtual dtor.  Source code at end.

First, a minor detour: while I was doing this, I also determined that MSVC
1.52 and 2.2 still both contain a large flaw in initialization.  (v1.50 had
this, too):

 class clown { };
 clown bozo;      // pay no attention to the programming _style_
 clown &returnref()
 {
     return bozo;
 }
 void sideshowbob()
 {
     clown &crusty( returnref() );  // fails
     clown ronald( returnref() );  // passes
 }

Borland compiles this fine.  MSVC 2.2 gives errors C2061 (syntax error:
identifier 'returnref') and C2530 (references must be initialized).
Disappointing.  This has been in C++ for a very long time, and is pretty
clearly discussed in the ARM sections 8.4 and 8.4.3.

Anyway, here's the source code for the EasyWin, 32-bit Console app and DOS
app versions; the 32-bit Windows code is pointlessly longer, if someone
really wants it, email me.

#ifdef __BORLANDC__
# include <iostream.h>
#else
# include <ostream.h>
#endif

struct Base1 { virtual ~Base1(); };
struct Base2 {         ~Base2(); };

struct Derived : public Base1, public Base2 { ~Derived(); };

Base1::~Base1()
{
 cout << " ~Base1";
}

Base2::~Base2()
{
 cout << " ~Base2";
}

Derived::~Derived()
{
 cout << " ~Derived";
}

int main()
{
 Derived *pDw = new Derived;
 Derived *pDx = new Derived;
 Derived *pDy = new Derived;
 Derived *pDz = new Derived;
 Base1 *pB1w = pDw;
 Base2 *pB2x = pDx;
 Derived *pDDy = pDy; // for completeness
 cout << "\npB1w==pDw:";
 delete pB1w;
 cout << "\npB2x==pDx:";
 delete pB2x;   // with VC++ 2.2, faults here.
 cout << "\npDDy==pDy:";
 delete pDDy;
 cout << "\npDz as is:";
 delete pDz;
 cout << "\n";
    return 0;
}

----------
(c) Copyright 1995 by Larry West; I hereby grant rights to copy
my contribution within this forum or in email exchanges for purposes
of discussion, as long as attributions are maintained. Editing for
brevity is encouraged.
----------
LarryWest@msn.com (MS Exchange or UUEncoded attachments only)
lwest@ix.netcom.com (MIME, BinHex, UUEncoded attachments okay)
---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]