Streamers, abstract base classes, and saving to TFiles

I’d like to understand default streamers and abstract classes.

I have a class, TGANEtaSlice, that I’d like to save in a TFile. The members of the class TGANEtaSlice include three pointers to VNetworkBase. VNetworkBase is a pure virtual class, from which classes corresponding to different libraries inherit. For the sake of discussion call these TNetworkA and TNetworkB (the actual inheritance structure involves more than one virtual layer, and I suspect it’s irrelevant to the question).

When I create a TGANEtaSlice via it’s regular constructor, I supply a filename, and a factory class decides at run time which of the classes that inherit from VNetworkBase should actually be instantiated.

Now initially, I assumed that to save TGANEtaSlice I’d have to do

VNetworkBase * pointer1; \\! do not persistify
VNetworkBase * pointer2; \\! do not persistify
VNetworkBase * pointer3; \\! do not persistify

Then use a custom streamer to actually fill in those pointers from other data members.
Otherwise the fact that a VNetworkBase has no default constructor (being pure virtual and not having a constructor at all) would cause issues. That was what I understood from reading this section; I/O of custom classes - ROOT

But then this question Class with a pointer to an abstract class as datamember talks about saving classes containing pointers to abstract classes, and does appear to directly persistify the abstract data pointer! Frustratingly, the code discussed in the question is no longer available, and the other question linked is a 404 error.

So, in theory;

  1. Can I save a class with a pointer to a pure abstract class and persistify the object that inherits from that pure abstract class automagicaly?
  2. If the answer to question 1 is “yes” why isn’t the lack of default constructor for VNetworkBase a showstopper?
  3. And, also if the answer to 1 is “yes”, some practical questions;
    • Which classes need a ClassDef? TGANEtaSlice surely does, I think TNetworkA and TNetworkB to as well, but I’m not sure if VNetworkBase does?
    • Which classes need to inherit from TObject? My impression was that none of them have to (from I/O of custom classes - ROOT)
    • What goes in the linkdef? Would every single class want an entry like; #pragma link C++ class CLASSNAME?

I can think of more than one way round this issue, but maybe it should just work and what I’ve got already now is only slightly off.

Many thanks, Henry


ROOT Version: 6.24/06
Platform: NAME=“CentOS Linux” VERSION=“7 (Core)” ID_LIKE=“rhel fedora” CLUSTER=“sunrise”
Compiler: using GNU Make 3.82, which presumably calls g++ (GCC) 11.2.0 under the hood.


1: Yes, you can save instance of a class deriving from an abstract class by having of data member of type pointer to the abstract base class.

2: Because the I/O will call the equivalent of new MostDerivedClass() which in turn will construct the base classes (abstract or not).

3:

Which classes need a ClassDef?

ClassDef is compulsory only for class inheriting from TObject (or any base class that has a ClassDef). If you are going to use ClassDef it will need to be use in all the classes in the hierarchy.

Which classes need to inherit from TObject? My impression was that none of them have to

Correct (the only reason to inherit from TObject would be if you needed to use a TClonesArray or another ROOT collection.

What goes in the linkdef? Would every single class want an entry like; #pragma link C++ class CLASSNAME?

Yes. Don’t forget to request the current I/O mechanism by adding the trailing +:

#pragma link C++ class CLASSNAME+;
1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.