Pure virtual destructors in abstract classes

From: Nick West (n.west1@physics.oxford.ac.uk)
Date: Fri Nov 19 1999 - 09:59:41 MET


Dear roottalk,

I am getting rather confused trying to use multiple inheritance with an abstract
base class.  I can illustrate two problems I am having with two simple classes A
(abstract) and C (concrete).

A.h:-                                 

class A {
public:
 virtual ~A() =0;
 ClassDef(A,0)
};

A.cxx:-

#include "A.h"
ClassImp(A)

C.h:-

#include "A.h"
class C: public A {
public:
 virtual ~C() {}
 ClassDef(C,0)
};

C.cxx:-

#include "C.h"
ClassImp(C)

It all compiles and links but when I run ROOT there is something wrong:-

root [1] C* pc = new C;
root [2] delete pc;
31703:minfastjob: /sbin/loader: Fatal Error: Unresolved symbol in /minosdisk/sof
tware/OO/MINFAST_v1.2/lib.osf1/librlm.so: __dt__1AXv

Thanks to a mail from Mathew Langston to roottalk:-

  http://root.cern.ch/root/roottalk/roottalk99/1475.html

I finally figured out that I had to add to A.h:-

  A::~A() {}

That makes CINT still consider A abstract, but knows how to destruct it.
Next I changed C so that it inherited from TObject as well, i.e. in C.cxx:-

changed:-
  
  class C: public A {

to:-
  
  class C: public TObject, A {

Now I cannot even create a C object:-

root [0] C* pc = new C;
Error: Can't call C::C() in current scope FILE:/tmp/aaaaadpaa LINE:1

It becomes clearer if I construct on the stack:-
root [1] C c;
Error: abstract class object 'C c' declared FILE:/tmp/baaaadpaa LINE:1

and, sure enough, if I look:-

root [2] .class C
===========================================================================
class C
 size=0x18
 (tagnum=473,voffset=-1,isabstract=1,parent=-1,gcomp=0,=~cd=0)
...

tells me I have one abstract member. Now Mathew's trick no longer works and I
have to explicitly define a destructor for A in its header:-

  virtual ~A() {}

which solves the problem.  Other member functions can remain pure virtual, but
the destructor appears to be special. So, I can fix both problems but it has
taken me quite a long time to figure it out (the problems arose in a rather
larger program of course).  My first motivation for this mail is to get it into
roottalk just in case it saves somebody else some time.

The second reason is to ask for suggestions as to how people who are just 
starting out should proceed.  When a program halts complaining about 
unresolved symbol __dt__1AXv what should they do?  In my case I figured it was
something about CINT, but have no idea about __dt__ or the significance of the
Xv.  Is there somewhere that explains these symbols?  Are they platform
specific? - I am running on an Alpha/OSF Digital UNIX V4.0F C++ 6.1.

The second problem also took me a while to figure out.  CINT is great and if we
have to give it a helping hand from time to time then its a small price to pay,
but again, is where should I look up a limitation like this?

Cheers,

Nick West



This archive was generated by hypermail 2b29 : Tue Jan 04 2000 - 00:43:43 MET