Re: [ROOT] multiple inheritance from TObject

From: Christian Holm Christensen (cholm@hehi03.nbi.dk)
Date: Mon Apr 28 2003 - 19:53:28 MEST


Hi Benoit, 

Benoit Revenu <revenu@iap.fr> wrote concerning
  [ROOT] multiple inheritance from TObject [Mon, 28 Apr 2003 18:02:09 +0200 (METDST)] 
----------------------------------------------------------------------
> Dear Rooters,
> 
> I want a class to inherit from 2 others classes inheriting from TObject.
> I don't need this class to be in a dictionnary so that I DON'T get the 
> rootcint error message :
> -------------------------
> Warning: multiple ambiguous inheritance TObject and C. Cint will not get 
> correct base object address
>
> I would like to do something like :
> --------------------------------------------
> cat test.h:
> --------------------------------------------
> #include "TMinuit.h"
> #include "TObject.h"
> 
> class A : public TMinuit
> {
>   public:
>   A(){}
>   ~A(){}
>   int a;
>   ClassDef(A,1)
> };
> 
> class B : public TObject
> {
>   public:
>   B(){}
>   ~B(){}
>   int b;
>   ClassDef(B,1)
> };
> 
> class C : public A, public B
> {
>   public:
>   C(){}
>   //~C(){}
>   int c;
> };

Whoa - that's asking for a whole slew of problems.  What you have is
an ambiguity in the inheritance: 


       A       A        class A { public: int next;  } 
        \     /		class B : public A { void f(int); void g(char); }
         B   C          class C : public A { void f(int); void g(float); }
	  \ /		class D : public B, public C { void h(); void i(); }
           D  

Now, the standard clearly says that

  D::h() { B::next = C::next; } 

is well-formed, while 

  void D::h() { next = 0; } 

is ill-formed; the reason being that there's no way to know which
`next' (B::next inherited from A, or C::next inherited from _another_
A) is to be assigned.  Similar holds for member function lookup:
Either the compiler must be able to resolve the member function by
context (that is, via it's arguments), or you must explicitly qualify
the member function name:

  void D::i() { A::f(1L); } // Well-formed 
  void D::i() { f(1L); }    // Ill-formed 
  void D::i() { g('a'); }   // Well-formed - calls A::g(char)
  void D::i() { g(42); }    // Well-formed - calls B::g(float)

This is exactly the reason for the error you get 

> ../src/test.h: In method `C::~C ()':
> ../src/test.h:26: request for member `operator delete' is ambiguous
  
Another way to get out of this conundrum, is to use virtual
inheritance: 

           A            class A { public: int next;  } 
          / \ 		class B : virtual public A { void g(char); }
         B   C          class C : virtual public A { void g(float); }
	  \ /		class D : public B, public C { void h(); void i(); }
           D  
 
  
In this case, there's only _one_ (indirect) base object of class A,
and 

  void D::h() { next = 0; } // is well-formed 

However, virtual inheritance may imply a performance hit, as even more
calls have to be resolved via the virtual table. 

All this is explained in excruciating detail in the ISO/IEC standard,
section 10.1. 

Then there's the issue whether CINT supports virtual inheritance (I
don't know the answer to that question - anyone?). 

My advice, would be to avoid the multiple inheritance in the first
place for classes that you need I/O and interpretation capabilities.
Perhaps containment will do the job, or perhaps some sort of
indirection.  In `pure' C++ you can also use templates to `customise'
a class, an option which unfortunately isn't that well supported in
CINT (as you have to explicitly make instances and dictionaries for
those instances). 

In general, multiple inheritance is a very nifty feature of C++ that
you can use to do all sorts of cool things, but it's tricky business
and you need to keep it at a level where it's not really needed for
the casual user.  

Hope that clears things up a bit.  

Yours, 

 ___  |  Christian Holm Christensen 
  |_| |	 -------------------------------------------------------------
    | |	 Address: Sankt Hansgade 23, 1. th.  Phone:  (+45) 35 35 96 91
     _|	          DK-2200 Copenhagen N       Cell:   (+45) 24 61 85 91
    _|	          Denmark                    Office: (+45) 353  25 305
 ____|	 Email:   cholm@nbi.dk               Web:    www.nbi.dk/~cholm
 | |



This archive was generated by hypermail 2b29 : Thu Jan 01 2004 - 17:50:11 MET