Hi Alexis, I have fixed this special case with TRef when cloning an object. The fix is in CVS. Note that you do not need a Streamer function to handle this case. You do not have to set the parent. This is done automatically. Thanks for reporting this case and giving a simple example. Rene Brun On Fri, 18 Apr 2003, Mignon Alexis wrote: > 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 > >
This archive was generated by hypermail 2b29 : Thu Jan 01 2004 - 17:50:11 MET