Collectionクラスというのは、つまりc++オブジェクト(基本型も含む)をひとまとめにして管理するクラス。コンテナと呼ぶ場合もある。
rootのオブジェクト用にCollectionクラスが用意されていて、それがTCollection。TCollectionはTObjectを継承するすべてのクラスを管理できる。
TCollectionは代表的にはTListやTObjArray、TClonesArrayといった派生クラスをもつ。
例えばTCanvasはTListクラスをメンバー変数として持っていて、TH1などをDrawをする時、内部的にはTCanvasのTListにそのオブジェクトを加えるという動作をしている。
同じように、TFileもTListクラスをメンバー変数として持っていて、Writeメソッドを使用すると、内部的にはおのTListにオブジェクトが加わっている。
つまりはTCanvasもTFileもオブジェクトをコンテナにしまっているという性質は共通している。
TListは双方向リスト、TObjArrayは動的配列用クラスである。
TList *l = new TList(); l->Add(obj); ... l->At(num); //返り値はTObject* l->FindObject("name"); //オブジェクトを探す
TObjArray *a = new TObjArray(); a->Add(obj); ... (*a)[num]; //TObjArrayは演算子[]が使える a->At(num); //返り値はTObject* a->FindObject("name"); //オブジェクトを探す
いろいろメソッドが用意されているけど、下のような書き方をすることが(rootのソースコード中では)多い。
TList *l = new TList(); ... //l->Add(hoge); TIter next(l); TObject *obj; While( (obj = next()) ){ (THoge*)obj; ... }
TList *l = canvas->GetListOfPrimitives();
TList *l = file->GetListOfKeys(); //TKeyからobjectを呼び出すには key->ReadObj()
TCollectionを継承しているクラスはWriteすると、コンテナに収納されてるオブジェクトすべてが自動的にWriteされる。
どういうことかというと、
TList l(4); l.Add(o1); l.Add(o2); ... TFile *f = new TFile("file.root","recreate"); l.Write();
ここでfile.rootを開くと
[] .ls TFile** file.root TFile* file.root KEY: TObject o1;1 KEY: TObject o2;1 ...
となる。
TListの状態でWriteしたい場合は
l.Write("name",1);
とWriteの第二引数を1にする。
同じ設定のオブジェクトを作るときに、for loopを使ってnewをすることがあると思う。newは基本的にコストが高いのでloop中ではなるべく避けたい。ROOTではこういう時にはTClonesArrayを使う。
TClonesArray a("TH1F",10); //この時点でTH1Fオブジェクト10個分のメモリが確保されているらしい。
ここで生成されるオブジェクトは初期化されていないため
for(int i=0;i<10;++i){ new(a[i]) TH1F(Form("h%d",i),"",100,-10,10);//Form()を使って同一オブジェクト名を避けている }
などとする必要がある。