Error: base with only non-default constructor in class witho

With the following code

[code]class TPlot {
public:
TPlot(TH1* data, TH1* direct, TH1* resolved, bool log_b = true, bool lin_b = true);
//
};

class TPlot2 : public TPlot {
TPlot2& operator= (TPlot2 const&);
TPlot2(TPlot2 const&);
public:
TPlot2(TH1* data, TH1* direct, TH1* resolved, bool log_b = true, bool lin_b = true)
: TPlot(data, direct, resolved, log_b, lin_b) {};
//
};
[/code]

CINT gives me a error: base `TPlot' with only non-default constructor in class without a constructor

Why doesn’t the Compiler recognize that there IS a constructor for TPlot2? (CINT version 5.16.16)
As I can’t upgrade the Compiler, is there any workaround for this situation?

Hi,

as the message says: TPlot doesn’t have a default constructor. So TPlot2 cannot initialize its base by default. You have to either provide a default constructor or explicitly call the TPlot non-default constructor in the TPlot2 constructor’s initializer list. Check your favorite C++ book on how base class initialization works.

Cheers, Axel.

Hi,
as you see in the code above TPlot2 DOES call the TPlot non-default Ctor in the initalizer list:

TPlot2(TH1* data, TH1* direct, TH1* resolved, bool log_b = true, bool lin_b = true) : TPlot(data, direct, resolved, log_b, lin_b) //<< here it is {};
Still, CINT refuses to compile that, while gcc verion 3.4.6 has no problems with the code.

Hi,

yes, you’re of course right, I didn’t see that line. Given the code snipped you posted I cannot reproduce the problem. Could you post the actual code and the command you run that generates the error message you quote?

Cheers, Axel.

Hi,
I won’t post my original code because it’s a few hundred LOC, but the following little test gave me the same error:

[code]#include <TH1F.h>

class TPlot1 {
public:
TPlot1(TH1* data, TH1* direct, TH1* resolved, bool log_b = true, bool lin_b = true) {};
};

class TPlot2 : public TPlot1 {
TPlot2& operator= (TPlot2 const&);
TPlot2(TPlot2 const&);
public:
TPlot2(TH1* data, TH1* direct, TH1* resolved, bool log_b = true, bool lin_b = true)
: TPlot1(data, direct, resolved, log_b, lin_b) {};
};

void test() {
TH1F* dat = 0;
TH1F* dir = 0;
TH1F* res = 0;
TPlot2 theplot(dat, dir, res);
}
[/code]

The compilation command and complete error message are as follows:

root [0] .L test.C+ Info in <TUnixSystem::ACLiC>: creating shared library /afs/desy.de/user/m/mertz/root/rootue/./test_C.so /afs/desy.de/user/m/mertz/root/rootue/fileh1XD1W.cxx:47: error: base `TPlot1' with only non-default constructor in class without a constructor g++: /afs/desy.de/user/m/mertz/root/rootue/./fileh1XD1W.o: No such file or directory Error in <ACLiC>: Compilation failed! root [1]

Hi,

ROOT needs to be able to default construct objects for I/O purposes: it can’t tell what parameters to pass to the constructor for an object read from file. You can disable I/O for the class by putting
#pragma link C++ class TPlot2-;
(note the trailing “-”) into your Linkdef.h.
But I’d just implement a default constructor.

Cheers, Axel.

Hi, thanks for that information.

For a class that needs information to be created in a consistent state it makes no sense to provide a default constructor, so I would not provide one. IMHO it is a bit annoying that ROOT requires me to provide that constructor for purposes (namely the streamer) that the class never was intended for.

I did not find the Linkdef.h - where is it located or where should I put it, if I have to create a new one?

[quote]I did not find the Linkdef.h - where is it located or where should I put it, if I have to create a new one?[/quote]When using ACLiC you have to choice, you can either add the following lines at the end of your header file:

#ifdef __MAKECINT__ #pragma link C++ class TPlot2-; #endif
or you can strore those same lines into a file named test_linkdef.h (the _linkdef part is customizable via a rootrc file).

[quote]IMHO it is a bit annoying that ROOT requires me to provide that constructor for purposes (namely the streamer) that the class never was intended for. [/quote]This is actually a feature of ACLiC. ACLiC is automatically generating for you the (equivalent of) the linkdef file. In order to do so, we had to make a choice of default (I/O or not) and chose the most common case (enable I/O). If you were to generate the shared library via your own scripts and your own linkdef (and call to rootcint) you would have been force to express the choice (i.e. in that case the linkdef file is compulsory).

Cheers,
Philippe.