该文章内容整理自《C++ Primer Plus(第6版)》、《Effective C++(第三版)》、以及网上各大博客
RTTI是运行阶段类型识别的简称,是C++的新特性,旨在为程序在运行阶段确定对象的类型提供一种标准方法。注意RTTI只适用于包含虚函数的类。C++有3个支持RTTI的元素
dynamic_cast
dynamic_cast运算符能将使用一个指向基类的指针来生成一个指向派生类的指针。它不能回答指针指向的是哪类对象,但能回答是否可以安全地将对象地址赋给特定类型的指针
当为派生类向基类转换的上行转换时使用dynamic_cast是安全的,但无必要使用
当为基类向派生类转换的下行转换时(注意dynamic_cast只适合进行在多态类型间的转换,也即基类需要含虚函数,因为只有基类指针真正指向特定派生类对象其虚函数才有特定实现),此时只适用于基类指针指向派生类对象时将基类指针下行转换成派生类指针,也即基类指针本身就指向派生类对象的情况,此时系统会自动检查指针所指对象是否为派生类,如
class B { virtual void f() {}; };
class D : public B { virtual void f(){}; };
B* pb1 = new D;
B* pb2 = new B;
D* pd = dynamic_cast<D*>(pb1); //转换成功,注意有括号
D* pd2 = dynamic_cast<D*>(pb2); //转换失败,pd2为NULL
}
多重继承时也能跨多个层次进行下行转换,如在菱形继承里将间接基类的指向下行转换为最底层派生类指针,此时注意中间层需要虚继承
除了dynamic_cast外,C++还提供了static_cast、const_cast和reinterpret_cast,共四种显式类型转换符
- static_cast。适用于基本数据类型之间的转换;而对于类层次结构中基类和子类之间指针或引用的转换,进行上行转换是安全的,进行下行转换时,由于没有动态类型检查,所以是不安全的
- const_cast。用于将常量指针或引用被转化成非常量指针或引用,并且仍然指向原来的对象
- reinterpret_cast。用于任意指针或引用类型之间的转换、指针与足够大的整数类型之间的转换、从整数类型(包括枚举类型)到指针类型的转换
typeid
typeid运算符用于获取一个表达式的类型,其表达式可以为类型名称、变量名、数字、字符串、指针、结构体以及类等。其使用方法如下:
cout << typeid(int).name() << endl;
cout << typeid(1.23*3.4).name() << endl;
cout << typeid("hello").name() << endl;
cout << typeid(d).name() << endl;
cout << typeid(Date).name() << endl;
如果是声明了虚函数的类对象引用,则typeid()返回的是实际对象的类型信息,在运行时动态决定的;反之,则typeid()返回的是入参声明类型信息,在编译时静态决定的
type_info
typeid()返回的是type_info类的引用,因为该类的构造函数是private的,所以这个类不能拷贝,也不能自己构造。这个类对外提供了name(),operator==()等方法供用户使用
const type_info& t0 = typeid(int);
cout << t0.name() << endl;//t0.name()返回const char*类型
t1 == t2 ,t1 != t2 //还可以用来比较类型是否一致