Reputation: 600
Without RTTI and with virtual functions.
I encountered 2 different common solutions to provide type of the object:
with virtual method call and keep id inside the method:
class Base {
public:
virtual ~Base();
virtual int getType() const =0;
};
class Derived : public Base {
public:
virtual int getType() const { return DerivedID; }
};
with inline method call and keep id in the base class:
class Base {
int id_;
public:
virtual ~Base();
inline int getType() const { return id_; }
};
class Derived : public Base {
public:
Derived() { id_=DerivedID;}
};
What would be better choice in general and what is pro/cons of them?
Upvotes: 5
Views: 225
Reputation: 63946
Okay, I'll take a stab...
"What are the pros/cons of them?"
Your first example virtual int getType() const =0;
incurs extra processing overhead. A virtual
function call can be more difficult for a CPU to preempt. This issue may be trivial.
Your second example inline int getType() const { return id_; }
incurs extra runtime storage. And extra int
is stored for every instance of every Base
. This may also be trivial.
"What would be better choice in general?"
In general, avoid premature optimization. Choose the pure virtual function in the base class, because its correctness is enforced by the compiler and runtime.
Upvotes: 0
Reputation: 1
You don't need virtual inheritance from the immediate base class, or any base class member variables to support this feature at all
struct Interface {
virtual void foo() = 0;
virtual int bar() = 0;
};
template<class T>
class Base : public Interface {
public:
int getType() const { return getTypeId(); }
static int getTypeId() { return T::ClassId; }
};
class Derived : public Base<Derived> {
public:
static const int ClassId = DerivedID;
virtual void foo() { }
virtual int bar() { return 1; }
};
Usage is like
Derived der;
Interface* iface = &der;
iface->foo();
iface->bar();
See a working sample here.
NOTE:
All of the types you use with a current configuration of such system need to be well known at compile time. This doesn't support a Plugin pattern based mechanism.
Upvotes: 0
Reputation: 308530
If you choose the second option with an ID in every derived class, you'll have an extra member in every object you create. If you use the first option of a virtual function, you'll have an extra pointer in the vtable which only exists once per class, not per object. If the class will have more than one virtual function, the first option is clearly better. Even if not, I think it more closely corresponds to what people will expect.
Upvotes: 1