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.