RTTI
这个听上去银瓶乍破水浆迸铁骑突出刀枪鸣的名字正是我大C艹的运行阶段类型识别(Runtime Type Identification)的简称
RTTI可以通过基类的指针和引用来检测这些指针和引用所指向的派生类对象的具体类型.
假设有一个类层次结构,其中的类都是从一个基类派生而来的,则可以让基类指针指向其中的任何一个类的对象.在处理一些信息之后,选则一个类,并创建这种类型对象,然后返回这个对象的地址,而这个地址可以赋值给基类指针,那么如何确定这个对象的类型?
只有知道了类型,才可能调用类方法的正确版本,如果在这个类结构层次中,所有的成员都拥有虚函数,在这个时候就不需要知道对象的类型.但派生类可能包含一些新的方法,在这种情况下只有某些类型可以使用该方法.这时候就可以使用RTTI提供解决方案.
dynamic_cast 运算符:
这个运算符可以检测是否可以安全的将对象的地址赋值给特定的类型指针.
假设有下列类层次结构:
所以,问题”指针指向的是那种类型”和”类型转换是否安全”,类型是否安全更通用点.原因在于:要调用类方法.类型并不一定要完全匹配,儿科一是定义了方法的与你版本的基类类型.
dynamic_cast语法:
下列代码演示了这种处理,首先他定义了三个类.Grand类定义了一个虚函数Speak(),并且其他类都重定义了这个虚函数,Superb类定义了一个虚函数Say(),而Magn也重定义了他.程序定义了GetOne()函数用来随机创建这三种类中的某种类对象,并对其初始化,然后将地址作为Grand*指针返回并赋给pg.然后使用pg调用Speak().因为这个函数是虚的随意代码能够正确的调用指向的对象的Speak()版本.
typeid运算符和type_info类
typeid运算符使得能够确定两个对象是否为同种类型.他接受两种参数:
- 类名
- 结果为对象的表达式
typeid运算符返回一个对type_info对象的引用,其中type_info是在头文件typeinfo中定义的一个类.这个类重载了==和!=运算符,以便可以使用这些运算符来对类型进行比较.1typeid(Magn) == typeid(*pg); //如果pg指向的是一个Magn对象,则表达式结果为bool值.true,否则为false.
如果pg是一个空指针,则程序将引发bad_tyoeid异常.type_info包含了一个name()方法,该函数返回一个随着实现而异的字符串…通常是类名.
有瑕疵的RTTI例子:
不讨论大家对RTTI的争论,介绍一个应该避免的编程方式:
通过不使用dynamic_cast和虚函数,而使用typeid(),可将上述代码重写为:
上述代码不仅sb而且还有毛病..如果从Magn类派生出一个Insu的类,而后者需要重新定义Speak()和Say().则必须修改for循环,添加一个else if.但下面的语句适合所有从Grand派生出的类:
所以说如果发现ifelse中使用了typeid,则应该考虑是否使用虚函数和dynamic_cast