C++ RTTI
In this page:
What is RTTI?
RTTI, or Run-Time Type Information, is the mechanism C++ provides for determining the exact, actual type of an object while the program is running, rather than relying only on the static type known at compile time.
Example: What is RTTI?
#include <iostream>
#include <typeinfo>
class Animal {
public:
virtual ~Animal() {}
};
class Dog : public Animal {};
int main() {
Animal *a = new Dog();
std::cout << typeid(*a).name() << std::endl;
delete a;
return 0;
}
Login to try C/C++/Java/PHP code in the editor
The typeid Operator
The typeid operator returns an object representing the real runtime type of an expression, which you can compare against another typeid result or use to print a human-readable (if compiler-specific) name of the class involved.
Example: The typeid Operator
#include <iostream>
#include <typeinfo>
int main() {
int x = 5;
double y = 3.14;
std::cout << typeid(x).name() << " " << typeid(y).name() << std::endl;
return 0;
}
Login to try C/C++/Java/PHP code in the editor
Dynamic Cast on Pointers
The dynamic_cast operator safely converts a base class pointer into a derived class pointer, checking at runtime whether the object actually is of that derived type — if the cast isn't valid, it returns nullptr instead of producing an invalid pointer.
Example: Dynamic Cast on Pointers
#include <iostream>
class Animal {
public:
virtual ~Animal() {}
};
class Dog : public Animal {
public:
void bark() { std::cout << "Woof" << std::endl; }
};
int main() {
Animal *a = new Dog();
Dog *d = dynamic_cast<Dog *>(a);
if (d != nullptr) d->bark();
delete a;
return 0;
}
Login to try C/C++/Java/PHP code in the editor
Dynamic Cast on References
dynamic_cast also works on references, but since a reference can never be null, an invalid cast on a reference throws a std::bad_cast exception instead of silently returning a null value, which you're expected to catch if the cast might fail.
Example: Dynamic Cast on References
#include <iostream>
class Animal {
public:
virtual ~Animal() {}
};
class Dog : public Animal {
public:
void bark() { std::cout << "Woof" << std::endl; }
};
int main() {
Dog realDog;
Animal &a = realDog;
try {
Dog &d = dynamic_cast<Dog &>(a);
d.bark();
} catch (std::bad_cast &e) {
std::cout << "Invalid cast" << std::endl;
}
return 0;
}
Login to try C/C++/Java/PHP code in the editor
Best Practices with RTTI
RTTI checks carry a small but real runtime cost, so where possible it's preferable to design your class hierarchy around ordinary virtual function polymorphism, reserving RTTI for the specific cases — like certain plugin or serialization systems — where you genuinely need to inspect a type at runtime.
Example: Best Practices with RTTI
#include <iostream>
class Animal {
public:
virtual void speak() { std::cout << "..." << std::endl; }
};
class Dog : public Animal {
public:
void speak() override { std::cout << "Woof" << std::endl; }
};
int main() {
Animal *a = new Dog();
a->speak();
delete a;
return 0;
}
Login to try C/C++/Java/PHP code in the editor
Chapter Quiz — Complete all 11 topics to unlock
0/11 topics done
Complete these topics first: