Run-Time Type Information (RTTI) is a mechanism in C++ that allows the type of an object to be determined during runtime. While C++ is statically typed, meaning that type information is typically resolved at compile-time, RTTI enables certain scenarios where the type needs to be identified during program execution.
RTTI is primarily used in polymorphic situations, where a pointer or reference to a base class can point to objects of derived classes. It helps to discover the exact type of the object at runtime.
There are two primary components of RTTI in C++:
typeid Operatordynamic_cast Operatortypeid OperatorThe typeid operator allows you to query the type of an object at runtime. It returns a reference to a type_info object, which contains information about the type.
Syntax:
typeid(expression)
Where expression can be:
typeid will return the type of the actual derived object).Example:
#include <iostream>
#include <typeinfo>
class Base {
public:
virtual ~Base() {}
};
class Derived : public Base {};
int main() {
Base* basePtr = new Derived(); // Pointer to a derived object
std::cout << "Type of basePtr: " << typeid(*basePtr).name() << std::endl;
return 0;
}
In the example, typeid(*basePtr) will return the actual type of the object (Derived), not the static type (Base), because basePtr points to a Derived object. Note that typeid works correctly with polymorphic types (i.e., classes with at least one virtual function).
dynamic_cast OperatorThe dynamic_cast operator is used to safely cast a pointer or reference from one type to another in a class hierarchy, particularly for casting between base and derived classes.
It checks at runtime if the casting is valid:
nullptr (for pointer casts) or throws a std::bad_cast exception (for reference casts).Syntax:
dynamic_cast<new_type>(expression)
Where new_type is the type you want to cast to, and expression is the object being cast.
Example:
#include <iostream>
class Base {
public:
virtual ~Base() {}
};
class Derived : public Base {
public:
void derivedMethod() {
std::cout << "Derived class method called" << std::endl;
}
};
int main() {
Base* basePtr = new Derived(); // Pointer to base class pointing to derived object
Derived* derivedPtr = dynamic_cast<Derived*>(basePtr);
if (derivedPtr) {
derivedPtr->derivedMethod(); // Safe to call derived class method
} else {
std::cout << "Cast failed!" << std::endl;
}
return 0;
}
In this example, dynamic_cast<Derived*>(basePtr) successfully casts basePtr to a Derived*, and the method derivedMethod() can be called. If basePtr did not point to a Derived object, the cast would fail and derivedPtr would be nullptr.
dynamic_cast and typeid) works only with polymorphic types—classes that have at least one virtual function. If a class does not have any virtual functions, RTTI features like dynamic_cast will not work correctly.dynamic_cast, incurs a small runtime performance penalty because the system has to track type information and verify casts at runtime.typeid: Used to get type information of an object at runtime. Returns a type_info object.dynamic_cast: Used to safely cast pointers or references between base and derived classes. Ensures the cast is valid at runtime, avoiding unsafe conversions.