El RTTI(RunTime Type Identification) se puede usar para muchas cosas, lo más típico es invertir la herencia con un dynamic_cast:

    Base *ptr_base = ...;
    Derived *ptr = dynamic_cast<Derived*>(ptr_base);

Aquí las clase Derived hereda de Base, y un dynamic_cast permite saber si un puntero de tipo Base es en realidad de la clase Derived o no. Si devuelve algo distinto de 0 es que la conversión ha tenido éxito.

También se suele usar mucho el Typeid, tyepid( variable ) devuelve una clase que representa el tipo de esa clase, eso permite que los tipos se puedan comparar en tiempo de ejecución, obtener una representación en string del nombre de la clase typeid(variable).name()… etc.

Lo que no tenía tan claro es qué pasa cuando se hace algo como esto:

    Base *ptr = ... ;
    std::cout << typeid(*ptr).name() << std::endl;

¿Cuál es el resultado?

Para probarlo, aunque la Wikipedia ya lo sabía, un programita de ejemplo:

#include <typeinfo>
#include <iostream>

// Clase base 
class Base
{
public:
    virtual void action()  = 0;
    virtual ~Base() {}
};

// Una clase derivada de base...
class Derived : public Base
{
public:
    virtual void action()
    { std::cout << "Hi from Derived" << std::endl; }
    virtual ~Derived() {}
};

// Una clase derivada de base (indirectamente)...
class Derived2 : public Derived
{
public:
    virtual void action()
    { std::cout << "Hi from Derived II" << std::endl; }
    virtual ~Derived2() {}
};

void show(Base *base)
{
    std::cout << "Esta función recibe un puntero Base..." << std::endl;
    std::cout << "Puntero = " << (void*) base << " typeid = "
        << typeid(base).name() << std::endl;
    std::cout << "Realmente apuntado = " << typeid(*base).name() << std::endl;
    std::cout << std::endl;
}

int main()
{
    Derived  *ptr_d = new Derived();
    Derived2 *ptr_d2 = new Derived2();

    show(ptr_d);
    show(ptr_d2);
    // cast mu burro... pero valido.
    show( reinterpret_cast<Derived*>(ptr_d2) );

    delete ptr_d;
    delete ptr_d2;

    return 0;
}

y aquí su resultado:

Esta función recibe un puntero Base...
Puntero = 0x804a008 typeid = P4Base
Realmente apuntado = 7Derived

Esta función recibe un puntero Base...
Puntero = 0x804a018 typeid = P4Base
Realmente apuntado = 8Derived2

Esta función recibe un puntero Base...
Puntero = 0x804a018 typeid = P4Base
Realmente apuntado = 8Derived2

Efectivamente, devuelve la clase real … bien pensando es cómo tiene que ser 🙂