# RTTI: Run-Time Type Information

# Name of a type

You can retrieve the implementation defined name of a type in runtime by using the .name() member function of the std::type_info object returned by typeid.

#include <iostream>
#include <typeinfo>

int main()
{
    int speed = 110;

    std::cout << typeid(speed).name() << '\n';
}

Output (implementation-defined):

int

# dynamic_cast

Use dynamic_cast<>() as a function, which helps you to cast down through an inheritance hierarchy (main description).

If you must do some non-polymorphic work on some derived classes B and C, but received the base class A, then write like this:

class A { public: virtual ~A(){} };

class B: public A
{ public: void work4B(){} };

class C: public A
{ public: void work4C(){} };

void non_polymorphic_work(A* ap)
{
  if (B* bp =dynamic_cast<B*>(ap))
    bp->work4B(); 
  if (C* cp =dynamic_cast<C*>(ap))
    cp->work4C(); 
}

# The typeid keyword

The typeid keyword is a unary operator that yields run-time type information about its operand if the operand's type is a polymorphic class type. It returns an lvalue of type const std::type_info. Top-level cv-qualification are ignored.

struct Base {
    virtual ~Base() = default;
};
struct Derived : Base {};
Base* b = new Derived;
assert(typeid(*b) == typeid(Derived{})); // OK

typeid can also be applied to a type directly. In this case, first top-level references are stripped, then top-level cv-qualification is ignored. Thus, the above example could have been written with typeid(Derived) instead of typeid(Derived{}):

assert(typeid(*b) == typeid(Derived{})); // OK

If typeid is applied to any expression that is not of polymorphic class type, the operand is not evaluated, and the type info returned is for the static type.

struct Base {
    // note: no virtual destructor
};
struct Derived : Base {};
Derived d;
Base& b = d;
assert(typeid(b) == typeid(Base)); // not Derived
assert(typeid(std::declval<Base>()) == typeid(Base)); // OK because unevaluated

# When to use which cast in c++

Use dynamic_cast for converting pointers/references within an inheritance hierarchy.

Use static_cast for ordinary type conversions.

Use reinterpret_cast for low-level reinterpreting of bit patterns. Use with extreme caution.

Use const_cast for casting away const/volatile. Avoid this unless you are stuck using a const-incorrect API.