1、什么是RTTI?
RTTI:Run-Time Type Identification运行时类型识别
程序在运行时能够使用基类的指针或引用来检查这些指针或引用所指的对象的实际的派生类。
在这里要用到两个C++中的关键字:typeid和dynamic_cast
2、typeid
typeid是C++中一个用来获取变量类型的关键字,用法跟使用函数一样 typeid(xxx)
typeid注意事项:
(1)typeid返回的是一个type_info对象的引用,而这个引用是与具体的变量类型有关的,
也就是说不同的变量类型都有一个type_info结构体。type_info结构体如下:
class type_info{ public: const char* name() const; // 打印具体类型的方法 一般这样用 typeid(x1).name() bool operator==(const type_info& rhs) const; // 运算符重载 支持直接 typeid(x1) == typeid(x2) bool operator!=(const type_info& rhs) const; // 运算符重载 int before(const type_info& rhs) const; virtual ~type_info(); // 析构函数 private: ...... };
(2)xxx可以是一个变量名(typeid(a)),也可以是一个具体的变量类型(typeid(int)),通常是用来做比较的时候,如下例子所示:
int i = 0; cout << typeid(i).name() << endl; // int型变量 i cout << typeid(&i).name() << endl; // int *变量 &i
if (typeid(i) == typeid(int)) { }
(3)如果我们想通过基类的指针获得派生类的数据类型,基类必须带有虚函数,否则获取的就是基类的类型,并且只能够去获取派生类对象的实际类型,
也就是说我们typeid传参的时候只能是对象类型或者是对象引用,不能是对象指针(注意我这里说的是你想要通过基类获取派生类对象数据类型)
背景:因为我们可以通过基类的指针变量指向一个派生类变量的地址,而typeid关键字提供了使用基类指针去获取派生类对象的数据类型。
1 #include <iostream> 2 using namespace std; 3 4 class Fly1{ 5 public: 6 virtual void fly(void); // Fly1基类中含有虚函数 7 }; 8 9 class Fly2{ 10 public: 11 void fly(void) ; // Fly2基类中不含虚函数 12 }; 13 14 class Plane1 : public Fly1 // Plane1派生类继承于Fly1 15 { 16 public: 17 virtual void fly(void); 18 void transport(void); 19 }; 20 21 class Plane2 : public Fly2 // PLane2派生类继承于Fly2 22 { 23 public: 24 virtual void fly(void); 25 void transport(void); 26 }; 27 28 /****************************************/ 29 void Fly1::fly(void) 30 { 31 cout << "fly---Fly1" << endl; 32 } 33 34 void Fly2::fly(void) 35 { 36 cout << "fly---Fly2" << endl; 37 } 38 39 void Plane1::fly(void) 40 { 41 cout << "fly---Plane1" << endl; 42 } 43 44 void Plane2::fly(void) 45 { 46 cout << "fly---Plane2" << endl; 47 } 48 49 int main(void) 50 { 51 Fly1 *fly1 = new Plane1(); 52 Fly2 *fly2 = new Plane2(); 53 54 cout << typeid(fly1).name() << endl; 55 cout << typeid(*fly1).name() << endl; 56 cout << typeid(fly2).name() << endl; 57 cout << typeid(*fly2).name() << endl; 58 59 return 0; 60 }