Calling a class constructor (with parameters) by name

Hi,

Let’s assume I have a base class A:

class A
{
public:
A(SomeClassType*) = 0;
};

and that I’d like to be able to select, runtime, using just the name of the implementation class, which implementation to use, amongst B and C for instance.
If the ctor has no parameter, I sort of know how to do it, I’d use TClass::New(), but I do not see how to do it for ctors with parameters…

Thanks,

Hi,

TClass::New is only able to call one constructor without any parameter.
To call a constructor with parameters you need to go directly through
CINT. For example something like:A* = (A*)gROOT->ProcessLine("new B(\"tt\",\"xx\")");
Cheers,
Philippe

Hi,

But then I do not see how to pass a variable parameter to that ctor.
e.g. what if I’d like to automate the following code :

SomeClass driver = … some object;
Base* b = new A(driver);
or
Base* b = new B(driver);

How do I pass driver to gROOT ??

Hi,

using Driver* driver=...; A* a= (A*)gROOT->ProcessLine(Form("new B(0x%x)",driver));
That will pass the value of driver to the constructor B::B(Driver* driver).

You could also have a singleton DriverManager, which stores the current driver, and which gets contacted by B’s and C’s constructors, as in [code]B::B() {
Driver* driver=DriverManager::Instance()->GetCurrentDriver();
… }

A* CreateNewA(TClass* cl, Driver* driver) {
if (!cl->InheritsFrom(A::Class())) return 0;
DriverManager::Instance()->SetCurrentDriver(driver);
return static_cast<A*>(cl->New());
}

class DriverManager {
public:
static DriverManager* Instance() {
static DriverManager thatsMe; return &thatsMe;}
void SetCurrentDriver(Driver* driver) {fDriver=driver;}
Driver* SetCurrentDriver(Driver* driver) const {return fDriver;}
~DriverManager() {}
protected:
DriverManager(): fDriver(0) {}
private:
Driver* fDriver
};[/code]
Yes, that’s more lines, but it’s more regular C++, too :slight_smile:
Axel.

Hi,

The first solution with Form() would be enough for me, but the TROOT::ProcessLine method is supposed to return void, so how can that compile/work ?

OK, the method used should be ProcessLineFast.

Here’s a sample which seems to work (gcc4 on Mac OS 10.4.2, ROOT 5.04/00) :

[code]

#include
#include “TObjString.h”
#include “TROOT.h”

using namespace std;

class Base
{
public:
virtual ~Base() {}
virtual void print() = 0;
};

class A : public Base
{
public:
virtual ~A() {}
A(TObjString* s) : fString(*s) {}
void print() { cout << “A:” << fString.String().Data() << endl; }
private:
TObjString fString;
};

class B : public Base
{
public:
virtual ~B() {}
B(TObjString* s) : fString(*s) {}
void print() { cout << “B:” << fString.String().Data() << endl; }
private:
TObjString fString;
};

void test(const char* type, const char* name)
{
TObjString* s = new TObjString(name);
Base* b = reinterpret_cast<Base*>(gROOT->ProcessLineFast(Form(“new %s((TObjString*)%p)”,type,s)));
b->print();
}

[/code][/u]