You are here

How to use the ClassDef Preprocessor Macro?

ClassDef is a C preprocessor macro that must be used if your class derives from TObject. It can be used if you simply want to enhance your class, see this paragraph. ClassDef contains member declarations, i.e. it inserts a few new members into your class. No per-object data member is added.

The ClassDef macro family (read on and you will see that there are more) is defined in the file Rtypes.h. This file is referenced by all ROOT include files, so you will automatically get them if you use a ROOT include file.

To apply ClassDef() to your class, insert it somewhere in your class's definition. It contains its own private and public tags so it can be added to either a private or public part of a class definition.

class MyClass: public TObject {
   ClassDef(MyClass, 2); //The class title
};

The ClassDef macro takes two arguments: the class name and the class version. There can be a comment after the ClassDef macro which ROOT shows in some contexts.

ClassDef and the Class Name

The class name must be stated without the enclosing namespace, i.e. for

class A::B

you will write

namespace A {
  class B {
    ClassDef(B, 2); // An example
  };
}

For templates you can use ClassDef too, without template arguments; see e.g. the header file for TParameter.

ClassDef and the Class Version

You will need to increase the version number whenever you change the definition of your class, or ROOT will not be able to handle objects written before and after this change in one process. Start counting at 2. The version number 0 (zero) disables I/O for the class - which makes sense for classes that are purely transient (e.g. a factory, a helper class). We prefer 2 over 1; the latter had a special meaning in some contexts.

Changes that happen within the definition of a base class, or changed within the definition of a class type of a data member, do not require incrementing the class version; ROOT will handle that itself. Only member changes (type, addition, removal, renaming) of immediate data members require incrementing of the class version.

See e.g. TLine.h for a real life application of ClassDef.

ROOT I/O Requirements for Classes

To be able to store objects with ROOT they must have a default constructor, i.e. one that can be called without arguments:

class MyClass: public TObject {
  public:
    MyClass(int i = 0); // default constructor
    ClassDef(MyClass, 1); //The class title
  };

ClassDef Variants

Virtual Functions

ClassDef assumes that your class has a virtual function table, and so it adds a few virtual functions to it. This in turn means that if you should declare your destructor as virtual:

   ...
   virtual ~MyClass();

If you don't have virtual functions, and if you do not plan to derive from the class, then you can use the ClassDefNV version of the macro. It's like ClassDef, only it assumes that there is no inheritance involved.

Override

ClassDef does not mark functions as override. ClassDefOverride does! Use the latter to avoid warnings about override inconsistency, where your functions use override while those from ClassDef don't.

Inline

If your class does not have a source file (common for templates), and if you do not want to provide a dictionary, you can use ClassDefInline. It comes with ClassDefInlineNV and ClassDefInlineOverride variants. Note that the I/O performance for the use of ClassDefInline and friends is slightly worse than that of the original, non-inline versions.

Dictionaries: ClassDef Member Definitions

ClassDef declares a few members to your class. Some of them are inline, but some need to have an implementation. ROOT generates it automatically as part of the dictionary. We have documentation on how to generate a dictionary with rootcling. Genreflex can also deal with ClassDef classes and TObject inheritance.

If you do not create the dictionary for your class you will have missing symbols at link time (e.g. ShowMembers()), because ClassDef declares class members but they are not implemented anywhere!

Why ClassDef?

You must use it if your class derives from TObject. You can use it even if not. It enables features like ROOT's introspection mechanism (obj->IsA() returning a TClass*). And it increases the I/O speed, even though ROOT I/O will also work without. The amount of that speed improvement depends on so many things that we cannot give a precise number; it saves a map lookup per object stored.

Does ClassDef modify the layout of the objects in memory?

No, it does not. The ClassDef macro adds useful static information, more specifically public static member functions, to the class and not to its instances.

(Legacy) ClassDef and Documentation

The comment after ClassDef is used as the title of the class's TClass object. In the old days, ClassDef and ClassImp were needed for THtml. Currently, THtml is not used anymore by ROOT; its use is deprecated.