My base class must provide an interface to get a value that is dependent solely on the type of the derived class. I can think of two ways of implementing this:
Solution A, virtual functions:
class Base
{
public:
virtual ~Base() = default;
virtual int get_plain_value() const = 0;
};
class A final: public Base
{
public:
int get_plain_value() const override
{
return 42;
}
};
class B final: public Base
{
public:
int get_plain_value() const override
{
return 35;
}
};
Solution B, variable on base class:
class Base
{
public:
virtual ~Base() = 0;
int get_plain_value() const
{
return plain_value;
}
protected:
int plain_value;
};
Base::~Base() {}
class A final: public Base
{
public:
A()
{
plain_value = 42;
}
};
class B final: public Base
{
public:
B()
{
plain_value = 35;
}
};
Solution A is more robust (i.e. base class can not "forget" to set the value), and uses less memory (I have one new entry in vtable, which is per class, instead of one new variable per object).
But solution B is faster and much simpler from compiler's perspective, so much that get_plain_value()
is most likely inlined, and the value is simply read directly from the object memory, avoiding a function call entirely.
Is there a third option with benefits from both approaches? What is the recommended solution in these cases?
template <> int plain_value<A>() { return 42; }; template <> int plain_value<B>() { return 35; }
. This will only work if the callers are themselves templated or dedicated to a specific implementation.