I have heard a lot of people say any usage of typeid
is bad design, yet to me it seems like it offers great utility.
typeid
"bad design"?typeid
acceptable?typeid() can be much faster than other type checks if all the stars are aligned, or it can be extremely slow. typeid() requires the compiler to determine if a pointer is null, so if you already know your pointer is non-null, it's more efficient to use typeid() on a reference instead.
The typeid operator allows the type of an object to be determined at run time. The result of typeid is a const type_info& . The value is a reference to a type_info object that represents either the type-id or the type of the expression, depending on which form of typeid is used.
The typeid operator returns an lvalue of type const type_info that represents the type of our value.
The typeid operator returns an lvalue of type const std::type_info that represents the type of expression expr. You must include the standard template library header <typeinfo> to use the typeid operator. Classes A and B are polymorphic; classes C and D are not.
The problem isn't with typeid
. The problem is that seeing typeid
would encourage you to write this:
PolymorphicType *pType = ...;
if(typeid(*pType) == typeid(Derived1))
pType->Func1();
else if(typeid(*pType) == typeid(Derived2))
pType->Func2();
else if(typeid(*pType) == typeid(Derived3))
pType->Func3();
This is what we call "really stupid". This is a virtual function call done in about the least reasonable way possible. typeid
has the potential for abuse when used to replace dynamic_cast
and virtual
functions.
This example may sound far-fetched. After all, it's obvious that this is just a virtual call. But bad code often grows from the path of least resistance; all it takes is for one person to do a typeid() == typeid()
, and the seed of this code has begin. In general, if you're directly using typeid
frequently, odds are very good that you're doing something that could be better done with other language constructs.
typeid
is the polymorphic type deduction method of last resort.
Is all usage of typeid
wrong? Of course not. boost::any
wouldn't be possible without it. Well it would be possible, but it wouldn't be any safer than void*
. typeid
is what makes type-safe boost::any
type erasure possible. There are other legitimate uses of it.
But in code-lines-to-use ratio, I would suggest it should be in about one in 10,000 lines of code, at most. Much fewer than that, and you're probably using it wrong.
Is type checking slow?
In general, the main reason to call typeid
is either in templated code (as in boost::any
) or when you're expecting a polymorphic type. If the type is statically determined (ie: a typename or value of a non-polymorphic type is given), then you can expect it to be done at compile-time.
It's polymorphic values you should be concerned about. I've seen a performance test that showed that some typeid
implementations actually walk the class hierarchy, so the time it takes for them to find the type is proportional to the number of classes between the real type and the given type. Every implementation will be different, but that's a pretty good indication that maybe you shouldn't put it in performance-critical code.
I don't think anyone says that usage of typeid
is itself bad design; rather, what you'll hear is that usage of typeid
is indicative of bad design. The idea there is that any logic that distinguishes (say) Square
from Circle
should actually be in those classes, so should be expressed by a virtual function (polymorphism).
Needless to say, this is not an absolute rule.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With