Re: rootcint and multiple inheritance

From: Rene Brun (Rene.Brun@cern.ch)
Date: Mon Feb 14 2000 - 19:49:38 MET


Valeri,
To do I/O, you have to modify the Bclass::Streamer function.
See my changes in the files below:

Rene Brun

//--------------file LinkDef.h
#ifdef __CINT__

#pragma link off all globals;
#pragma link off all classes;
#pragma link off all functions;

#pragma link C++ class Aclass;
#pragma link C++ class Bclass-;

#endif



//---------------test.h
#include "TObject.h"

class Aclass
{
 protected:
  int   a_member_private;

 public:
  Aclass(){}
  Aclass(int apr, int apu) { a_member_private=apr; a_member_public=apu; }
  virtual ~Aclass(){}

  int   a_member_public;

  int GetApr()   const {return a_member_private;}
  int GetApu()   const {return a_member_public;}
  int PrintA()   const { printf("PrintA: %d %d \n",
a_member_private,a_member_public); }
  void SetApr(int apr) {a_member_private=apr;}
  
  //  ClassDef(Aclass,1)   // if this line commented - a_member is hidden
from root
};

class Bclass
      :public TObject
      ,public Aclass
{
  private:
  int b_member;

 public:
  Bclass();
  Bclass( int apr, int apu, int bpr );
  virtual ~Bclass(){}
  void Print() const { PrintA(); printf("PrintB:  a_priv= %d  a_publ= %db=
%d\n", GetApr(), GetApu(), b_member); }

  ClassDef(Bclass,1)
};


//-------------file test.cxx
#include "test.h"
   ClassImp(Bclass)
   
Bclass::Bclass() :Aclass()
{
   b_member = 1234;
}
Bclass::Bclass( int apr, int apu, int bpr ) : Aclass( apr, apu )
{
   b_member = bpr;
}
//______________________________________________________________________________
void Bclass::Streamer(TBuffer &R__b)
{
   // Stream an object of class Bclass.

   if (R__b.IsReading()) {
      Version_t R__v = R__b.ReadVersion(); if (R__v) { }
      TObject::Streamer(R__b);
      R__b >> b_member;
      int apr;
      R__b >> apr; SetApr(apr);
      R__b >> a_member_public;
   } else {
      R__b.WriteVersion(Bclass::IsA());
      TObject::Streamer(R__b);
      R__b << b_member;
      R__b << GetApr();
      R__b << GetApu();
   }
}


On Mon, 14 Feb 2000, Valeri Tioukov wrote:

> Dear Rene,
> 
> On Sun, 13 Feb 2000, Rene Brun wrote:
> 
> > Hi Valeri,
> > 
> > Yes, this is possible. see your files slightly modified below:
> > Run the script creating the shared lib test.so, then run the session:
> > Root > gSystem->Load("test");
> > Root > Bclass b;
> > Root > b.Dump();
> 
> the output of last command is:
> 
> root [2] b.Dump();             
> b_member                 1234        
> fUniqueID                0           object unique identifier
> fBits                    50331648    bit field status word
> 
> so a_member is not visible. 
> 
> As I stated in 1-st email I need to store the elements of Aclass (Bclass
> is only container) into root file and to make them available for
> root-analisys with minimal efforts. 
> I think that this problem is fearly actual for users who have
> non-Root C++ working applications.
> 
> The following example illustrates that this double inheritance scheme does
> not work as desired:
> 
> 
> //--------test.h------------
> #include "TObject.h"
> 
> class Aclass
> {
>  private:
>   int   a_member_private;
> 
>  public:
>   Aclass(){}
>   Aclass(int apr, int apu) { a_member_private=apr; a_member_public=apu; }
>   virtual ~Aclass(){ }
> 
>   int   a_member_public;
> 
>   int GetApr()   const {return a_member_private;}
>   int GetApu()   const {return a_member_public;}
>   int PrintA()   const { printf("PrintA: %d %d \n", a_member_private,a_member_public); }
> 
> };
> 
> class Bclass
>       :public TObject
>       ,public Aclass
> {
>   private:
>   int b_member;
> 
>  public:
>   Bclass(){}
>   Bclass( int apr, int apu, int bpr );
>   virtual ~Bclass(){}
> 
>   void Print() const { PrintA(); printf("PrintB:  a_priv= %d  a_publ= %db= %d\n", GetApr(), GetApu(), b_member); }
> 
>   ClassDef(Bclass,1)
> };
> //---------end of test.h-------------
> 
> //-------test.cxx file---------
> #include "test.h"
>    ClassImp(Bclass)
>    
> Bclass::Bclass( int apr, int apu, int bpr ) : Aclass( apr, apu )
> {
>    b_member = bpr;
> }
> //-------end of test.cxx file---------
> //-------b.C - test macro-----------
> void w()
> {
>   gSystem->Load("test");
>   Bclass ob(10,20,30);
>   ob.Print();
>   TFile f("test.root","RECREATE");
>   ob.Write("ob");
>   f.Write();
>   f.Close();
> }
> 
> void r()
> {
>   TFile *f = new TFile("test.root");
>   Bclass *ob = (Bclass*)f->Get("ob");
>   ob->Print();
>   TBrowser *br = new TBrowser();
> }
> 
> void t()
> {
>   TFile f("test.root","UPDATE");
> 
>   TTree *tree = new TTree("T","test tree");
>   Bclass  *pb = new Bclass();
>   TBranch *branch = tree->Branch("Bclass", "Bclass", &pb, 64000,1);
> 
>   for(int i=0; i<100; i++) {
>     pb = new Bclass(i,i,i);
>     tree->Fill();
>   }
> 
>   f.Write();
>   f.Close();
> }
> //-------end of b.C - test macro-----------
> 
> now if we do:
> 
> root [0] .L b.C
> root [1] w()                 // print on the screen and write to file
> PrintA: 10 20 
> PrintB:  a_priv= 10  a_publ= 20  b= 30
> root [2] t()                 // write the root tree
> root [3] r()                 // read from file and print on the screen
>  PrintA: 0 0 
> PrintB:  a_priv= 0  a_publ= 0  b= 30
> 
> we see that the elements of Aclass did not stored did not dumped and
> did not inspected correctly by root.
> No wonder, because rootcint do not generate streamer and showmember 
> stuff for members of Aclass: in testcint* files there are nothing
> appropriate.
> 
> Moreover: if I inspect tree by the graphical browser and double click on
> fBits it's blocks compleatly the root session (why BTW?). (Root 2.23/12 /RH5.1)
> 
> 
> So I repeate the original question: is it possible to make the members of
> Aclass available for storage in the root file and for root-analisys
> without any changements in Aclass body?
> 
> 
> Best regards
> Valeri
> 
> 
> 
> 
> 
> > 
> > Rene Brun
> > 
> > //----script to create a small shared lib on Linux
> > rootcint -f testcint.cxx -c test.h LinkDef.h
> > g++ -g -fPIC -I$ROOTSYS/include -c testcint.cxx test.cxx
> > g++ -g -Wl,-soname,test.so -shared testcint.o test.o -o test.so 
> > 
> > 
> > //----LinkDef.h file
> > #ifdef __CINT__
> > 
> > #pragma link off all globals;
> > #pragma link off all classes;
> > #pragma link off all functions;
> > 
> > #pragma link C++ class Bclass;
> > 
> > #endif
> > 
> > 
> > //-----test.h
> > #include "TObject.h"
> > 
> > class Aclass
> > {
> >  private:
> >   int   a_member;
> > 
> >  public:
> >   Aclass(){}
> >   virtual ~Aclass(){}
> > 
> >   //  ClassDef(Aclass,1)   // if this line commented - a_member is hidden
> > from root
> > };
> > 
> > class Bclass
> >       :public TObject
> >       ,public Aclass
> > {
> >   private:
> >   int b_member;
> > 
> >  public:
> >   Bclass();
> >   virtual ~Bclass(){}
> > 
> >   ClassDef(Bclass,1)
> > };
> > 
> > //-------test.cxx file
> > #include "test.h"
> >    ClassImp(Bclass)
> >    
> > Bclass::Bclass() :Aclass()
> > {
> >    b_member = 1234;
> > }
> > 
> > 
> > On Wed, 9 Feb 2000, Valeri Tioukov wrote:
> > 
> > > Hi Rooters,
> > > 
> > > If I have class  Aclass  used by external application and I do not want to
> > > do ANY changement in this class, but I'd like to make it's memebers and
> > > functions visible to Root system (for storage and analisys purpose)
> > > inheriting new Bclass as following:
> > > 
> > > class Bclass
> > >       :public TObject
> > >       ,public Aclass
> > > 
> > > Is it possible?
> > > 
> > > I investigate that without including macros   ClassDef(Aclass,1) into the
> > > body of Aclass  rootcint do not generate  Streamer() and  
> > > ShowMembers() functions. Just mentioning of Aclass in LinkDef.h do not
> > > helps.
> > > 
> > > So it seems that the answer is NOT: it is not possible to make the members
> > > of classA visible to Root without changements of classA body.
> > > 
> > > But the same question was asqued at least twice:
> > > 
> > > http://root.cern.ch/root/roottalk/roottalk98/1986.html
> > > http://root.cern.ch/root/roottalk/roottalk98/0107.html
> > > 
> > > and in both cases the answers were a bit confusing but positive.
> > > 
> > > Why do not find the definite answer and add it to FAQ? 
> > > 
> > > I used for tests:
> > > ----------------test.h------------
> > > #include "TObject.h"
> > > 
> > > class Aclass
> > > {
> > >  private:
> > >   int   a_member;
> > > 
> > >  public:
> > >   Aclass(){}
> > >   virtual ~Aclass(){}
> > > 
> > >   //  ClassDef(Aclass,1)   // if this line commented - a_member is hidden  from root
> > > };
> > > 
> > > class Bclass
> > >       :public TObject
> > >       ,public Aclass
> > > {
> > >   private:
> > >   int b_member;
> > > 
> > >  public:
> > >   Bclass():Aclass(){}
> > >   virtual ~Bclass(){}
> > > 
> > >   ClassDef(Bclass,1)
> > > };
> > > -----------------------------------
> > > 
> > > ---------LinkDef.h----------------------
> > > #ifdef __CINT__
> > > 
> > > #pragma link off all globals;
> > > #pragma link off all classes;
> > > #pragma link off all functions;
> > > 
> > > #pragma link C++ class Aclass;
> > > #pragma link C++ class Bclass;
> > > 
> > > #endif
> > > ---------------------------------------
> > > 
> > > 
> > > Without the commented line command
> > > 
> > >  >  rootcint -f test_h.C -c test.h LinkDef.h
> > > 
> > > do not care about members of Aclass.
> > > 
> > > 
> > > Best regards
> > > Valeri
> > > 
> > 
> > 
> 



This archive was generated by hypermail 2b29 : Tue Jan 02 2001 - 11:50:18 MET