Advanced Gotchas
The typeid That Saw Only the Base
a base reference reveals less than the object holds
struct PlainBase {};
struct PlainDerived : PlainBase {};
struct PolymorphicBase {
virtual ~PolymorphicBase() = default;
};
struct PolymorphicDerived : PolymorphicBase {};
int main() {
PlainDerived plain;
PlainBase& plain_view = plain;
PolymorphicDerived dynamic;
PolymorphicBase& dynamic_view = dynamic;
std::cout << (typeid(plain_view) == typeid(PlainDerived)) << '\n';
std::cout << (typeid(dynamic_view) == typeid(PolymorphicDerived)) << '\n';
}
Run it. Which base reference exposes its derived object?
Why¶
typeid(expression) uses an expression's dynamic type only when its static class type is
polymorphic. PlainBase has no virtual function, so typeid(plain_view) is determined from
its static type; the virtual destructor makes PolymorphicBase polymorphic and enables the
second lookup. A virtual base from virtual inheritance is a different feature and does not meet
this requirement by itself. GCC emits no warning under -Wall -Wextra.
The fix¶
Give a base a virtual function when callers need runtime type identification:
Takeaway: typeid needs a polymorphic base (a virtual function), not virtual inheritance.
Try it: g++ -std=c++17 main.cpp -o demo && ./demo