[ROOT] TRef, Streamers et Clone()

From: Mignon Alexis (mignon@ganil.fr)
Date: Thu Apr 17 2003 - 16:39:35 MEST


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