【C++ typeid】
RTTI(Run-Time Type Identification,运行时类型识别),它使程序能够获取由基指针或引用所指向的对象的实际派生类型,即允许“用指向基类的指针或引用来操作对象”的程序能够获取到“这些指针或引用所指对象”的实际派生类型。在C++中,为了支持RTTI提供了两个操作符:dynamic_cast和typeid。
typeid返回一个变量的类型描述对象。返回类型为type_info,此类型定义在typeinfo头文件中。只能在有virtual函数的类对象使用。
class Base {}; class Derived: public Base {}; int main() { Base b, *pb; pb = NULL; Derived d; cout << typeid(int).name() << endl << typeid(unsigned).name() << endl << typeid(long).name() << endl << typeid(unsigned long).name() << endl << typeid(char).name() << endl << typeid(unsigned char).name() << endl << typeid(float).name() << endl << typeid(double).name() << endl << typeid(string).name() << endl << typeid(Base).name() << endl << typeid(b).name()<<endl << typeid(pb).name()<<endl << typeid(Derived).name() << endl << typeid(d).name()<<endl << typeid(type_info).name() << endl; return 0; }
分别用MS的V8和GUN的GCC编译该段代码并运行,结果分别为下面的左右二图。
1、不包含 virtual 的例子。
Base *pb2 = dynamic_cast<Base *>(new Derived); Base &b2 = d; Base *pb3 = &d; cout << typeid(pb2).name() <<endl//输出Base * << typeid(b2).name()<<endl //输出Base << typeid(pb3).name()<<endl//输出Base * << typeid(*pb3).name()<<endl;//输出Base
因为Base不包含虚函数,所以typeid的结果指出,表达式的类型是Base或Base *型,尽管他们的底层对象是Derived。即:当typeid操作符的操作数是不带有虚函数的类类型时,typeid操作符会指出操作数的类型,而不是底层对象的类型。
2、加上 virtual 的例子。
class Base {virtual void f(){}; }; /*...*/ cout << typeid(pb2).name() <<endl//输出Base * << typeid(b2).name()<<endl //输出Derived << typeid(pb3).name()<<endl//输出Base * << typeid(*pb3).name()<<endl;//输出Derived
这次Base含有虚函数,注意看结果,指针仍然是Base*的,尽管他们指向的是底层对象Derived,而这些Base对象的类型却是Derived的。
因为指针pb3不是类类型,所以typeid就返回该指针pb3的指针类型Base *。而*pb3是一个类类型的表达式,而且该类带有虚函数,所以指出该pb3指向的底层对象的类型Derived。
参考:
1、http://www.cnblogs.com/ustc11wj/archive/2012/08/11/2637319.html
2、http://blog.csdn.net/goodlixueyong/article/details/6244303