运行时类型识别(Run-time type identification , RTTI),是指在只有一个指向基类的指针或引用时,确定所指对象的准确类型的操作。其常被说成是C++的四大扩展之一(其他三个为异常、模板和名字空间)。
使用RTTI的两种方法:
1、typeid()
第一种就像sizeof(),它看上像一个函数,但实际上它是由编译器实现的。typeid()带有一个参数,它可以是一个对象引用或指针,返回全局typeinfo类的常量对象的一个引用。可以用运算符“= =”和“!=”来互相比较这些对象,也可以用name()来获得类型的名称。如果想知道一个指针所指对象的精确类型,我们必须逆向引用这个指针。比如:
#include <typeinfo> #include <iostream> #include <cmath> using namespace std; class Shape { public : int area(float r) { float s=3.14*pow(r,2); return s; } }; int main() { Shape* shape=new Shape; cout<< typeid(*shape).name()<<endl; system("pause"); }
运行结果为:
为了保持一致性,typeid()也可以用于内部类型,所以下面的表达式结果为true:
typeid(36) == typeid(int) typeid(0) == typeid(int) int i; typeid(i) == typeid(int) typeid(&i) ==typeid(int*)
可以用typeid 检查基本类型和非多态类型:
//可以用typeid 检查基本类型和非多态类型: #include <typeinfo> #include <iostream> using namespace std; typedef unsigned int UINT ; int main() { cout<< typeid(UINT).name()<<endl; cout<< typeid(string).name()<<endl; system("pause"); }
运行结果如图所示:
用typeid分析指针与引用的区别:
#include <typeinfo> #include <iostream> using namespace std; class B { public: virtual double fun() { return 0.1; } }; class D :public B { }; int main() { B *p = new D; B &r = *p; //无名对象照样有别名 cout<<(typeid(p)==typeid(B*)); //仅指向子类中父类部分 cout<<(typeid(p)!=typeid(D*)); //而非指向整个子类对象 cout<<(typeid(r)==typeid(D)); //引用的类型却是子类的 cout<<(typeid(*p)==typeid(D)); //间址访问的是子类对象 cout<<(typeid(*p)!=typeid(B)); //而非父类 cout<<(typeid(&r)==typeid(B*)); //引用的地址是父类的 cout<<(typeid(&r)!=typeid(D*)); //而非子类的 system("pause"); return 0; }
运行结果:
2、dynamic_cast <type-id> (expression)
#include <typeinfo> #include <iostream> using namespace std; class Shape { public: virtual void Draw() { } }; class Circle:public Shape { public: virtual void Draw() { } }; int main() { Shape* sp=new Circle; Circle* cp=dynamic_cast<Circle*>(sp); if(cp) cout<<"cast successful"<<endl;; system("pause"); }
运行结果:
如何使用RTTI: