Re: [ROOT] TRef, Streamers et Clone()

From: Mignon Alexis (mignon@ganil.fr)
Date: Fri Apr 18 2003 - 11:11:23 MEST


Hi René,

I use the version 3.05/00 on a linux platform

| root [11] c3->GetParent()
| (class TestClass*)0x899c098
| root [12] c
| (class TestClass*)0x899c098

That's not what i want . I would like c3->GetParent() to return the 
address of c2. With the automatically generated streamer it returns 0, 
i would have thought it would return the address of c.

So I've customized the streamer :

 void TestClass::Streamer(TBuffer &R__b)
 {
    // Stream an object of class TestClass.

   UInt_t R__s, R__c;
   if (R__b.IsReading()) {
      Version_t R__v = R__b.ReadVersion(&R__s, &R__c); if (R__v) {
} TObject::Streamer(R__b);
      R__b >> fList;

////// that's what i've added //////////
      TIter next(fList);
      TestClass2*c2;
      while( (c2=(TestClass2*)next()) ){
        c2->SetParent(this);
      }
/////////////////////////////////////////////
      R__b.CheckByteCount(R__s, R__c, TestClass::IsA());
   } else {
      R__c = R__b.WriteVersion(TestClass::IsA(), kTRUE);
      TObject::Streamer(R__b);
      R__b << fList;
      R__b.SetByteCount(R__c, kTRUE);
   }
 }

i thought - naively - that it would then set the TRef to the address 
of the object being build through the streamer.

So what must i do to correctly set the TRefs of the objects in the list 
so that they actually point to their real parent ?
can it be done through the streamer ?

Le Jeudi 17 Avril 2003 17:56, vous avez écrit :
| Hi Alexis,
|
| Unfortunately, you do not indicate which version of Root and OS.
| I cannot reproduce your problem. Using your .H and .C files, I have
| created a shared lib mignon.so, then run the following session:
|
| root [0] .L mignon.so
| root [1] TestClass* c=new TestClass;
| root [2] c->Add("first");
| root [3] c->Add("second");
| root [4] c->Add("third");
| root [5] c.ls()
| OBJ: TestClass  TestClass       test class : 0 at: 0x899c098
| root [6] TestClass* c2=(TestClass*)c->Clone();
| root [7] c2.ls()
| OBJ: TestClass  TestClass       test class : 0 at: 0x89a37d0
| root [8] TestClass2* c3=(TestClass2*)c2->GetList()->First();
| root [9] c3
| (class TestClass2*)0x89d2368
| root [10] c3.ls()
| OBJ: TestClass2 first   testclass2 : 0 at: 0x89d2368
| root [11] c3->GetParent()
| (class TestClass*)0x899c098
| root [12] c
| (class TestClass*)0x899c098
|
| AS you can see, results seem to be correct.
|
| Rene Brun
|
| Mignon Alexis wrote:
| > Hello,
| >
| > I have a problem with some circular refernces when i try to make a
| > clone of an object.
| >
| > i have for instance 2 objects :
| >
| > /////////////////// TestClass.H ///////////////////////
| >
| > #ifndef __TestClass__
| > #define __TestClass__
| >
| > #include <TList.h>
| > #include "TestClass2.H"
| > class  TestClass2;
| > class  TestClass : public TObject {
| > protected :
| >   TList *fList; // -> list
| >
| > public :
| >   TestClass();
| >   ~TestClass();
| >
| >   TestClass2* Add(const Char_t *name);
| >   TList* GetList() const;
| >   ClassDef(TestClass,1) //test class
| > };
| >
| > inline TList*TestClass::GetList() const{
| >   return fList;
| > }
| >
| > #endif
| > \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
| > and
| > /////////////// TestClass2.H ///////////////////////////
| > #ifndef __TestClass2__
| > #define __TestClass2__
| >
| > #include <TNamed.h>
| > #include <TRef.h>
| > #include "TestClass.H"
| >
| > class TestClass;
| > class TestClass2 : public TNamed{
| > protected:
| >   TRef fClassTest; // back reference
| >
| > public:
| >   TestClass2();
| >   TestClass2(const Char_t* name, TestClass* tc);
| >   ~TestClass2();
| >
| >   TestClass* GetParent();
| >   void SetParent(TestClass*c);
| >
| >   ClassDef(TestClass2,1) //test class 2
| >
| > };
| >
| > inline TestClass* TestClass2::GetParent(){
| >   return (TestClass*)fClassTest.GetObject();
| > }
| >
| > #endif
| >
| > \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
| >
| > with the default streamer when i do
| >
| > TestClass* c=new TestClass;
| > c->Add("first");
| > c->Add("second");
| > c->Add("third");
| >
| > TestClass* c2=(TestClass*)c->Clone();
| >
| > TestClass2* c3=(TestClass2*)c2->GetList()->First();
| >
| > then
| > c3->GetParent() returns the null pointer (why not the pointer to c
| > ?)
| >
| > to set the parent member of TestClass2
| >
| > i've modified the streamer of TestClass so that it does a
| > class2->SetParent(this) for each object in its list.
| >
| > but then
| >
| > c3->GetParent() returns the pointer to c instead of c2 .
| >
| > What must i do in order to get the good parent pointer to the clone
| > of the first object
| >
| > this is the source code for the 2 classes :
| >
| > ////////////////////////// TestClass.C ////////////////////////////
| >
| > #include "TestClass.H"
| > #include <TCollection.h>
| >
| > ClassImp(TestClass);
| >
| > TestClass::TestClass(){
| >   fList=0;
| > }
| >
| > TestClass::~TestClass(){
| >   if(fList) {
| >     fList->Delete();
| >     delete fList;
| >   }
| > }
| >
| > TestClass2* TestClass::Add(const Char_t*name){
| >   if (!fList) fList=new TList;
| >   TestClass2*c=new TestClass2(name, this);
| >   fList->Add(c);
| >   return c;
| > }
| > void TestClass::Streamer(TBuffer &R__b)
| > {
| >    // Stream an object of class TestClass.
| >
| >    UInt_t R__s, R__c;
| >    if (R__b.IsReading()) {
| >       Version_t R__v = R__b.ReadVersion(&R__s, &R__c); if (R__v) {
| > } TObject::Streamer(R__b);
| >       R__b >> fList;
| >       TIter next(fList);
| >       TestClass2*c2;
| >       while( (c2=(TestClass2*)next()) ){
| >         c2->SetParent(this);
| >       }
| >       R__b.CheckByteCount(R__s, R__c, TestClass::IsA());
| >    } else {
| >       R__c = R__b.WriteVersion(TestClass::IsA(), kTRUE);
| >       TObject::Streamer(R__b);
| >       R__b << fList;
| >       R__b.SetByteCount(R__c, kTRUE);
| >    }
| > }
| >
| > \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
| >\\\\\
| >
| > and
| >
| > ////////////////////////// TestClass2.C
| > //////////////////////////// #include "TestClass2.H"
| >
| > ClassImp(TestClass2);
| >
| > TestClass2::TestClass2(){
| >   fClassTest=0;
| > }
| >
| > TestClass2::TestClass2(const Char_t *name, TestClass* tc)
| >
| >   : TNamed(name,"testclass2"){
| >
| >   fClassTest=tc;
| > }
| >
| > TestClass2::~TestClass2(){
| > }
| >
| > void TestClass2::SetParent(TestClass *c){
| >   fClassTest=c;
| > }
| > \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
| >\\\\ --
| > Alexis Mignon
| > GANIL
| > Bd Henri Becqurel
| > 14076 CAEN Cedex 5
| > France
| > tel: +(33) (0)231454680
| > e-mail : mignon@ganil.fr

-- 
Alexis Mignon
GANIL
Bd Henri Becqurel
14076 CAEN Cedex 5
France
tel: +(33) (0)231454680
e-mail : mignon@ganil.fr



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