<typeinfo>
The <typeinfo>
header is part of the C++ Standard Library that provides runtime type identification (RTTI) support. It allows programs to obtain information about object types at runtime. This header is particularly useful when working with polymorphic types and when you need to determine the type of an object dynamically.
std::type_info
class for representing type informationtypeid
operator for obtaining type information of expressions and typesstd::bad_typeid
exception classtypeid
and type_info
#include <iostream>
#include <typeinfo>
#include <string>
class Base {
public:
virtual ~Base() {}
};
class Derived : public Base {};
int main() {
int i = 5;
double d = 3.14;
std::string s = "Hello";
Base* b = new Derived();
std::cout << "Type of i: " << typeid(i).name() << std::endl;
std::cout << "Type of d: " << typeid(d).name() << std::endl;
std::cout << "Type of s: " << typeid(s).name() << std::endl;
std::cout << "Type of *b: " << typeid(*b).name() << std::endl;
delete b;
return 0;
}
typeid
operator is used to get the type_info
of various objects..name()
member function returns a C-style string representing the name of the type.Base*
, typeid(*b)
returns the type of the actual object pointed to (Derived)..name()
is implementation-defined and may vary between compilers.type_info
#include <iostream>
#include <typeinfo>
class Animal {
public:
virtual ~Animal() {}
};
class Dog : public Animal {};
class Cat : public Animal {};
void identifyAnimal(Animal* animal) {
if (typeid(*animal) == typeid(Dog)) {
std::cout << "This animal is a Dog" << std::endl;
} else if (typeid(*animal) == typeid(Cat)) {
std::cout << "This animal is a Cat" << std::endl;
} else {
std::cout << "Unknown animal type" << std::endl;
}
}
int main() {
Animal* dog = new Dog();
Animal* cat = new Cat();
Animal* generic_animal = new Animal();
identifyAnimal(dog);
identifyAnimal(cat);
identifyAnimal(generic_animal);
delete dog;
delete cat;
delete generic_animal;
return 0;
}
typeid
is used to compare the runtime type of objects.==
operator is used to compare type_info
objects returned by typeid
.bad_typeid
Exception#include <iostream>
#include <typeinfo>
class Base {
public:
virtual ~Base() {}
};
int main() {
try {
Base* ptr = nullptr;
std::cout << typeid(*ptr).name() << std::endl;
} catch (const std::bad_typeid& e) {
std::cout << "Caught bad_typeid exception: " << e.what() << std::endl;
}
return 0;
}
typeid
on a null pointer of a polymorphic type throws a std::bad_typeid
exception.type_info::before()
for Type Ordering#include <iostream>
#include <typeinfo>
#include <vector>
#include <algorithm>
class A {};
class B : public A {};
class C {};
bool compareTypes(const std::type_info* a, const std::type_info* b) {
return a->before(*b);
}
int main() {
std::vector<const std::type_info*> types = {
&typeid(int),
&typeid(double),
&typeid(A),
&typeid(B),
&typeid(C),
&typeid(std::string)
};
std::sort(types.begin(), types.end(), compareTypes);
for (const auto& type : types) {
std::cout << type->name() << std::endl;
}
return 0;
}
type_info::before()
is used to establish an ordering between types.type_info
pointers and sort them based on this ordering.#include <iostream>
#include <typeinfo>
class Base {
public:
virtual ~Base() {}
};
class DerivedA : virtual public Base {};
class DerivedB : virtual public Base {};
class MostDerived : public DerivedA, public DerivedB {};
void printType(Base* ptr) {
std::cout << "Actual type: " << typeid(*ptr).name() << std::endl;
}
int main() {
Base* b1 = new DerivedA();
Base* b2 = new DerivedB();
Base* b3 = new MostDerived();
printType(b1);
printType(b2);
printType(b3);
delete b1;
delete b2;
delete b3;
return 0;
}
typeid
correctly identifies the most derived type.Performance Impact: RTTI can have a performance cost, especially in large hierarchies. Some compilers allow disabling RTTI for performance-critical code.
Compiler Differences: The string returned by type_info::name()
is implementation-defined and may vary between compilers.
Use with Caution: Overreliance on RTTI can lead to brittle designs. It's often better to use virtual functions for polymorphic behavior.
Cross-Module Issues: RTTI might not work correctly across module boundaries in some implementations.
Memory Management: Remember that typeid
doesn't affect the lifetime of its operands. Proper memory management is still necessary.
The <typeinfo>
header in C++ provides runtime type identification capabilities:
std::type_info
class, which represents type information.typeid
operator is used to obtain type_info
objects for types and expressions.std::bad_typeid
for exception handling related to RTTI operations.RTTI, provided through <typeinfo>
, is a powerful feature that allows C++ programs to make decisions based on the types of objects at runtime. This is particularly useful in scenarios involving polymorphism, where the exact type of an object may not be known at compile time.
However, it's important to use RTTI judiciously. Overuse can lead to code that is hard to maintain and potentially less efficient. In many cases, proper use of virtual functions and polymorphism can provide better design solutions than relying on explicit type checking.
When used appropriately, the facilities provided by <typeinfo>
can be valuable tools for creating flexible and robust C++ programs, especially when dealing with complex class hierarchies or when implementing generic programming techniques that need to adapt to different types at runtime.