Type checking in C++

Homam picture Homam · Jan 4, 2011 · Viewed 39.3k times · Source

In C++, I want to know whether the actual type of the object is from the same class, not the same class or a derived one. This is similar to the following C# code:

Class Base
{
}

Class Child:Base
{
}

Base childObject = new Child();

If (childObject.GetType() == typeof(Child))
{
 // do some code
}

Thanks!

Answer

templatetypedef picture templatetypedef · Jan 4, 2011

There are two ways that you can do this. First, you can use the typeid operator, which returns a type_info structure containing information about the type of the object. For example:

Base* ptr = /* ... */
if (typeid(*ptr) == typeid(DerivedType)) {
    /* ... ptr points to a DerivedType ... */
}

Notice that you have to use typeid(*ptr) and not typeid(ptr) here. If you use typeid(ptr), then you'll get back a type_info object for Base*, since the pointer has type Base* regardless of what it points at.

An important point to note is that this will check if what ptr points at is exactly a DerivedType. If ptr is pointing at an object of a type derived from DerivedType (maybe an EvenMoreDerivedType), this code will not work correctly.

An alternative way of checking whether you are pointing at an object of some type that is a bit more robust is to use the dynamic_cast operator. dynamic_cast performs a checked typecast at runtime that will yield a valid pointer if the cast succeeds and nullptr otherwise. For example:

Base* ptr = /* ... */;
auto* derived = dynamic_cast<DerivedType*>(ptr);
if (derived) {
    /* ... points to a DerivedType ... */
}

This has the added advantage that if ptr points at something like an EvenMoreDerivedType, the cast will still succeed because EvenMoreDerivedType inherits from DerivedType.

As a final thought, you sometimes see code like this:

Base* ptr = /* ... */
if (auto* derived = dynamic_cast<DerivedType*>(ptr)) {
     /* ... points to a DerivedType ... */
}

This locally-scopes the derived pointer to the body of the if statement and uses the fact that nonzero values evaluate to true in C++. I personally find this easier to read and less error-prone, but by all means go with what's easiest for you.

Hope this helps!