Writing ROOT Classes
Introduction

ROOT Documentation

TObject

Default Constructor

Machine Indep Types

CLHEP classes

Collections

Pointers to other Objects

Byte-Ordering

LinkDef Files

A Skeleton

Introduction

ROOT Documentation

The first place to start is the ROOT User's Guide, Chapter 13 Adding a Class.

TObject

All ROOT classes should derive (inherit from) TObject.  For example:

class McEvent : public TObject 

In addition, to use Run Time Type Identification (RTTI) and object I/O - which you will want if you expect to write your ROOT object to a file - then you need to insert the following macros in your ROOT class:

First inside the class declaration, in the header file:
ClassDef(ClassName,ClassVersionID)  //The class title
For example:

class McEvent : public TObject {

ClassDef(McEvent,1)  // The Monte Carlo Event
};

Next inside the class source file, there will be:
ClassImp(ClassName)

The Default Constructor

Event ROOT class must have a default constructor.  Be sure, that the default constructor does not allocate any memory - this will cause a memory leak.

Machine Independent Types

Since different machines may have different lengths for the same type - ROOT provides a set of predefined types that are guaranteed to be machine independent.  For a full list of the available types see the Rtypes.h file in your $ROOTSYS/include directory.

When defining your class, be sure to use the machine independent types.  Here is a list:

Char_t      signed character 1 byte
UChar_t   unsigned character 1 byte
Short_t     signed short integer 2 bytes
UShort_t  unsigned short integer 2 bytes
Int_t         signed integer 4 bytes
UInt_t      unsigned integer 4 bytes
Float_t     float 4 bytes
Double_t double 8 bytes
Bool_t     boolean 0 false, 1 true

NOTE: Long_t and ULong_t are not yet machine independent - do not use them!!!

CLHEP Classes

ROOT provides many of the same types of classes that CLHEP does.  It is necessary to use the ROOT equivalent of the CLHEP classes, for example:

CLHEP CLASS ROOT Equivalent
HepPoint3D TVector3
HepLorentzVector TLorentzVector
   

Collections

Often you will want to store a collection of objects.  ROOT provides a variety of mechanisms to accomplish this.  

TObjArray
Stores objects derived from TObject.  The items stored in the TObjArray are not necessarily all objects of the same class.

TClonesArray
Stores objects derived from TObject that are identical - i.e. they are all from the same class and have the same size.  Hence, objects stored in a TClonesArray cannot dynamically allocate any memory.

STL

It is also possible to use the STL classes:  vector, map, etc.  There is an example in the Skeleton section below.

Pointers to other objects

In general pointers should not be stored in a ROOT class.  However, if you wish to reference a ROOT object that is also stored in another branch - you can do so using TRef.

Byte-Ordering

For an introduction, please see Rene Brun's post to roottalk.

Basically, we want to be aware of the compiler's desire to order data members on byte boundaries.  What is a 8-byte boundary?  Or a 4-byte boundary?

An 8-byte boundary is an address that is divisible by 8 without any remainder.  For example a double which is 8 bytes would reside in bytes 0 to 7.

For example, 2-byte data members will be stored on 2-byte boundaries, 4-byte data members will be stored on 4-byte boundaries, etc.  To do so, it may be necessary to insert padding to move a data member to appropriate boundary.  We would like to avoid padding as much as possible since it wastes space and creates more work when trying to read in the data.  

We keep this in mind when ordering our data members in our classes.  Rene provided an example:

class MyClass { 
  Int_t fI1; 
  Double_t fD1; 
  Short_t fS1; 
  Bool_t fB1; 
  Double_t fD2; 
  Int_t fI2; 
  Someclass *fSomec; 
  Int_t fI3; 
}

Resulting in the following:
_ _ _ _  _ _ _ _   _ _ _ _ _ _ _ _  _ _   _    _ _ _ _ _   _ _ _ _ _ _ _ _
    fI1        pad                   fD1         fS1  fB1
      pad              fD2
Where we wasted 9 bytes due to padding.

Instead we can do:
class MyClass { 
  Double_t fD1; 
  Double_t fD2; 
  Int_t fI1; 
  Int_t fI2; 
  Int_t fI3; 
  Short_t fS1; 
  Bool_t fB1; 
  Someclass *fsomec;
}

Resulting in:
_ _ _ _ _ _ _ _  _ _ _ _ _ _ _ _  _ _ _ _  _ _ _ _  _ _ _ _  _ _   _
         fD1                         fD2           fI1           fI2          fI3      fS1  fB1

LinkDef Files

If you are adding a class to an existing ROOT class package, you will notice a file named *LinkDef.h.  This file is used when generating ROOT streamer methods.  These methods are used to actually perform the ROOT I/O.  You do not need to worry about this - except the following:

For each ROOT class, there must be a line declaring the class in the *LinkDef.h file.  For example:

#pragma link C++ class McEvent+;

A Skeleton

Here is an example ROOT class:
ExClass.h    ExClass.cxx

 

Back to GLAST ROOT    Back to GLAST Software Home

H. Kelly Last Modified:  2002-04-25 09:07:00 -0700