Re: Including none-TObjects

Rutger van der Eijk (r36@nikhef.nl)
Mon, 23 Mar 1998 16:59:06 +0100 (MET)


Hi Fons,

Thanks for your reply. At the moment I'm not using pointers to
non-TObjects so thats oke for now.

There is still a thing which is not completly clear for me. What should I
include in my none-TObject class declaration to make rootcint able to
generate the Streamer member function? Including only the Streamer
declaration gives error messages like:

Error: Can't call MTChannelId::Class_Version() in current scope FILE:
LINE:0
Error: No symbol MTChannelId::Class_Version() in current scope FILE:
LINE:0
Class MTChannelId: ShowMembers() not declared

or should I just include ALL the member functions as are 'defined' by
using the ClassDef 'statement'? (or which ones AT LEAST?)

(Actually my reason to make a few none-TObject classes is because of my
fear (or ignorance) of introducing to much 'overhead datamembers bytes'
in some low-level classes. I by now found out (i.e. have read) that every
TObject contains 8 bytes of datamembers. On a class which only has 2
bytes of 'real' datamemebers (and from which I will create millions of
instances) this seems as a waste of memory/disk space. What is exactly
written in this fBits and fUniqueID data member of TObjects? Is it
(almost) the same for all instances, so that I can expect a huge
compression factor? Or am I wise by not inheriting from TObject for these
essential, low size classes?)

Thanks, and keep up the good work,

Rutger van der Eijk

On Mon, 23 Mar 1998, Fons Rademakers wrote:

> Hi Rutger,
>
> for non-TObject classes you need to provide a custom TBuffer &operator>>()
> and TBuffer &operator<<() in case you want to be able to save the objects
> via pointers to such objects. In case you want to save directly the objects
> (as opposed to pointers to objects) you need only a Streamer().
> The default generated Streamer() should be ok (depending if you use pointers
> to basic types, in which case you need to make a custom Streamer()).
> For example:
>
> class MPipo : public TObject { <-- base class goes via TObject::Streamer()
> private:
> MAap fAap; <-- goes via MAap::Streamer()
> MNoot *fNoot; <-- goes via TBuffer &operator<<(), fNoot can be 0
> ...
> };
>
> A good example of a class having its own operator<< and operator>> is
> http://root.cern.ch/root/html/src/TArray.cxx.html and see also
> http://root.cern.ch/root/html/src/TArrayC.cxx.html for special operator>>.
>
> In case you don't want rootcint to generate the Streamer() and operator>>
> you have to put in the LinkDef.h file:
>
> #pragma link C++ class TArrayC-!;
>
> where - means no Streamer() and ! no operator>>() (can also be only !
> or -).
>
> Currently objects containing non-TObject derived objects can not
> be stored in Trees in split mode. For this and other rules see:
> http://root.cern.ch/root/HowtoWriteTree.html
>
> Cheers, Fons.
>
>
> Rutger van der Eijk wrote:
> >
> > Hi All,
> >
> > I'm having problems including some none-TObjects into a (root)shared
> > library.
> >
> > I have a simple Event class (MTRawEvent) declared as follows:
> > (some members not shown for clarity):
> >
> > ---- MTRawEvent.H ----
> > #ifndef _MTRawEvent_H_
> > #define _MTRawEvent_H_
> >
> > #include "TObject.h"
> > #include "MTRawHit.H"
> >
> > class MTRawEvent: public TObject {
> > public:
> > MTRawEvent(); // create uninitialized
> >
> > void SetRawHit(MTRawHit rawHit); // temp set hit as long as not array...
> > MTRawHit GetRawHit() const; // temp get the single raw hit
> >
> > virtual ~MTRawEvent(); // destroy Event-object
> >
> > ClassDef(MTRawEvent, 1) // RawEvent class
> > private:
> > MTRawHit fRawHit; // raw hit
> > };
> >
> > #endif // _MTRawEvent_H_
> > ---- ----
> >
> > It contains a MTRawHit object as datamember, which is NOT a TObject:
> >
> > ---- MTRawHit.H ----
> > #ifndef _MTRawHit_H_
> > #define _MTRawHit_H_
> >
> > #include "MTChannelId.H"
> >
> > class MTRawHit {
> > public:
> > MTRawHit(MTChannelId channelId = 0, Int_t tdcValue = 0);
> >
> > MTChannelId GetChannelId() const; // get channel id
> > Int_t GetTDCValue() const; // get TDC value
> >
> > ~MTRawHit(); // destroy Hit-object
> >
> > private:
> > MTChannelId fChannelId; // channel Id
> > Int_t fTDCValue; // TDC value
> > };
> >
> > #endif // _MTRawHit_H_
> > ---- ----
> >
> > It contains as datamembers a Int_t and another none-TObject class
> > MTChannelId.
> >
> > My problem:
> >
> > The MTRawEvent I (ofcourse) want to somewhere put in a TTree and a TFile.
> > With rootcint I can then create the appropriate Streamer methods for
> > classes inheriting from TObject. From reading the ROOT tutorial and
> > 'course' and browsing the web-pages it doesn't become completely clear
> > to me what the best procedure is to handle none-TObject classes.
> >
> > My questions:
> >
> > - Should I (manually) write Streamer (and ShowMember) member functions for
> > the none-TObjects (MTRawHit and MTChannelId) or should I only modify the
> > TObject MTRawEvent?
> > - If I write (or modify) a Streamer member function definition should I
> > also put the declaration in the class declaration? Actually I don't
> > understand why this seems NOT to be necesarry for TObjects...
> > - Should I include classes of the none-TObjects in the linkdef.h file
> > (with #pragma link C++ class MTChannelId-; (or with also '!' ?))
> >
> > I would appriciate any help and/or simple-example ,
> >
> > Rutger van der Eijk
>
> --
> Org: CERN, European Laboratory for Particle Physics.
> Mail: 1211 Geneve 23, Switzerland Phone: +41 22 7679248
> E-Mail: Fons.Rademakers@cern.ch Fax: +41 22 7677910
>