Cpp-RTTI机制

RTTI概念

RTTI (Run Time Type Identification) 即运行时类型识别, 程序能够使用基类类型的指针或引用来检查来检查这些指针或引用所指的对象的实际派生类型.

RTTI机制的产生

C++ 是一种静态类型语言, 其具体类型是在编译器就确定的, 不能在运行时更改. 然而由于面向对象程序设计中多态性的要求, C++中的指针或引用, 可能指向与它实际类型不符的其他类型(子类). 有时我们需要将一个多态指针转换为其实际指针对象的类型, 此时就需要知道运行时的类型信息.

typeiddynamic_cast 操作符

RTTI提供了两个非常有用的操作符: typeiddynamic_cast.

  • typeid操作符: 返回指针和引用所指的实际类型
  • dynamic_cast操作符: 将基类类型的指针或引用安全的转换为其派生类类型的指针或引用

我们知道C++的多态性是有虚函数实现的, 对于多态性的对象, 无法在程序编译阶段确定对象的类型. 为了在运行时获得一个对象的类型, 可以使用typeid函数, 该函数返回一个对type_info类对象的引用, 要使用typeid时必须使用头文件<typeinfo>, 因为typeid是一个返回类型为type_info的引用, 因此, 首先看一下type_info

type_info

成员函数:

  • name(): 返回类型的名称
  • raw_name(): 返回名字编码(Name Mangling)算法产生的新名称.
  • hash_code(): 返回当前类型对应的hash值. hash值是一个可以用来标志当前类型的函数, 有点类型学生的学号, 公民的身份证号, 银行卡号等等. 不过hash值有赖于编译器的实现, 在不同的编译器下可能会有不同的整数, 但它们都能唯一的标识某个类型.

遗憾的是, C++标准只对type_info类做了很有限的规定, 不仅成员函数少, 功能弱, 而且各个平台的实现不一致. 例如最常用的name()函数, int类型和Base(类)类型在VC/VS下的输出结果分别是intclass Base, 而在GCC下的输出结果分别是i4Base.

C++标准规定, type_info类至少要有如下所示的4个public属性的成员函数, 其他的扩展函数编译器开发者可以自由发挥, 不做限制.

  1. const char *name() const: 返回一个能表示类型名称的字符串, 但是C++标准没有规定这个字符串是什么形式的, 因此出现了不同编译器返回的字符串形式不同的情况.
  2. bool before (const type_info &rhs) const: 判断一个类型是否位于另一个类型前面, rhs参数是一个type_info对象的引用, 但是C++标准并没有规定类型的排列规则, 不同的编译器有不同的排列规则, 程序员也可以自定义. 要特别注意的是, 这个排列顺序和继承顺序是没有关系的, 基类并不一定位于派生类的前面.
  3. bool operator==(const type_info &rhs) const: 重载运算符==, 判断两个类型是否相同, rhs参数是一个type_info对象的引用
  4. bool operator!=(const type_info &rhs) const: 重载运算符!=, 判断两个类型是否不同, rhs参数是一个type_info对象的引用