typeid allows to check the type of an expression:
typeid (expression)
This operator returns a reference to a constant object of type type_info that is defined in the standard header file <typeinfo>. This returned value can be compared with another one using operators == and != or can serve to obtain a null-terminated character sequence representing the data type or class name by using its name() member.
// typeid
#include <iostream>
#include <typeinfo>
using namespace std;
int main () {
int * a,b;
a=0; b=0;
if (typeid(a) != typeid(b))
{
cout << "a and b are of different types:";
cout << "a is: " << typeid(a).name() << '';
cout << "b is: " << typeid(b).name() << '';
}
return 0;
}
The results are:
a and b are of different types:
a is: int
* b is: int
|
|
When typeid is applied to classes typeid uses the RTTI to keep track of the type of dynamic objects. When typeid is applied to an expression whose type is a polymorphic class, the result is the type of the most derived complete object:
// typeid, polymorphic class
#include <iostream>
#include <typeinfo>
#include <exception>
using namespace std;
class CBase {virtual f(){} };
class CDerived : public CBase {};
int main () {
try {
CBase* a = new CBase;
CBase* b = new CDerived;
cout << "a is: " << typeid(a).name() << '';
cout << "b is: " << typeid(b).name() << '';
cout << "*a is: " << typeid(*a).name() << '';
cout << "*b is: " << typeid(*b).name() << '';
} catch (exception& e)
{ cout << "Exception: " << e.what() << endl; }
return 0;
}
The results are:
a is: class CBase *
b is: class CBase *
*a is: class CBase
*b is: class CDerived
|
|
Notice how the type that typeid considers for pointers is the pointer type itself (both a and b are of type class CBase *). However, when typeid is applied to objects (like *a and *b) typeid yields their dynamic type (i.e. the type of their most derived complete object).
If the type typeid evaluates is a pointer preceded by the dereference operator (*), and this pointer has a null value, typeid throws a bad_typeid exception.