15.4.2 RTTI的工作原理(3)
注意:即使编译器支持RTTI,在默认情况下,它也可能关闭该特性。如果该特性被关闭,程序可能仍能够通过编译,但将出现运行阶段错误。在这种情况下,您应查看文档或菜单选项。
程序清单15.17中程序说明了重要的一点,即应尽可能使用虚函数,而只在必要时使用RTTI。下面是该程序的输出:
正如您看到的,只为Superb和Magnificent类调用了Say( )方法(每次运行时输出都可能不同,因为该程序使用rand( )来选择对象类型)。
也可以将dynamic_cast用于引用,其用法稍微有点不同:没有与空指针对应的引用值,因此无法使用特殊的引用值来指示失败。当请求不正确时,dynamic_cast将引发类型为bad_cast的异常,这种异常是从exception类派生而来的,它是在头文件typeinfo中定义的。因此,可以像下面这样使用该运算符,其中rg是对Grand对象的引用:
2.typeid运算符和type_info类
typeid运算符使得能够确定两个对象是否为同种类型。它与sizeof有些相像,可以接受两种参数:
类名;
结果为对象的表达式。
typeid运算符返回一个对type_info对象的引用,其中,type_info是在头文件typeinfo(以前为typeinfo.h)中定义的一个类。type_info类重载了= =和!=运算符,以便可以使用这些运算符来对类型进行比较。例如,如果pg指向的是一个Magnificent对象,则下述表达式的结果为bool值true,否则为false:
如果pg是一个空指针,程序将引发bad_typeid异常。该异常类型是从exception类派生而来的,是在头文件typeinfo中声明的。
type_info类的实现随厂商而异,但包含一个name( )成员,该函数返回一个随实现而异的字符串:通常(但并非一定)是类的名称。例如,下面的语句显示指针pg指向的对象所属的类定义的字符串:
程序清单15.18对程序清单15.17作了修改,以使用typeid运算符和name( )成员函数。注意,它们都适用于dynamic_cast和virtual函数不能处理的情况。typeid测试用来选择一种操作,因为操作不是类的方法,所以不能通过类指针调用它。name( )方法语句演示了如何将方法用于调试。注意,程序包含了头文件typeinfo。
程序清单15.18 rtti2.cpp