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

From: Rene Brun (Rene.Brun@cern.ch)
Date: Thu Apr 17 2003 - 17:56:15 MEST


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