Skip to content Skip to sidebar Skip to footer

Access Overridden Field In Constructor Without Templates

I can't access field overridden in child class from parent C++ constructor and I can not use templates, because upstream project doesn't use them. This is working Python prototype

Solution 1:

Despite you're asking to do this without templates, it's the only way to do this from a base class constructor.

Here's a sample how it should be done:

structIDriver {
    // Public virtual API:virtualvoidfunc1()= 0;
    // ...virtual ~IDriver() {}
};

template<typename Derived>
classDriver : public IDriver {
public:
    Driver() {
         std::cout << "Driver" << std::endl;
         std::cout << static_cast<Derived*>(this)->name() << std::endl;
    }   
};

classSpecificDriver : public Driver<SpecificDriver> {
public:
    // Public virtual API:virtualvoidfunc1();
    std::string name()const{ return"SpecificDriver"; }
    // or use typeid(SpecificDriver).name() if you prefer
};

intmain(){
    SpecificDriver sd;
}

Live Demo


As for your comment:

Is it possible to use additional init() function as in @tobspr method, but making name a field instead of function call?

Well, since the class name is a static property of these classes anyway, you can use a static const field like follows:

template<typename Derived>
classDriver : public IDriver {
public:
    Driver() {
         std::cout << name << std::endl;
         std::cout << Derived::name << std::endl;
    }   

private:
    staticconst std::string name;
};

template<typename Derived>
const std::string Driver<Derived>::name = "Driver";

classSpecificDriver : public Driver<SpecificDriver> {
public:
    staticconst std::string name;
};

const std::string SpecificDriver::name = "SpecificDriver";

intmain(){
    SpecificDriver sd;
}

Live Demo

or even simplified use typeid():

#include<iostream>#include<string>#include<typeinfo>template<typename Derived>
classDriver {
public:
    Driver() {
         std::cout << typeid(*this).name() << std::endl;
         std::cout << typeid(Derived).name() << std::endl;
    }  
};

classSpecificDriver : public Driver<SpecificDriver> {
};

intmain(){
    SpecificDriver sd;
}

Live Demo

Solution 2:

Assuming you have two classes Base and Derived, the Base constructor does not know anything about the Derived class, which makes it impossible to distinguish between both types.

Since you also can not (should not) call virtual methods in the constructor, a common pattern is to make an init method:

structBase {
    virtual std::string get_name(){ return"Base"; }
    voidinit(){ std::cout << get_name(); }
};

structDerived : public Base {
    virtual std::string get_name(){ return"Derived"; }
};

// Later on ..
Base b;
b.init(); // Should print "Base"

Derived d;
d.init(); // Should print "Derived"

As you can see, this is definitely not the simplest solution. Using templates in this case would certainly be better.

Post a Comment for "Access Overridden Field In Constructor Without Templates"