RTTI 运行时类型识别

本文详细介绍了C++中的RTTI(运行时类型识别)机制,包括dynamic_cast操作符、typeid操作符和type_info类的工作原理及其使用场景。强调了RTTI主要用于含有虚函数的类层次结构,并提醒开发者在必要时使用,避免滥用。
摘要由CSDN通过智能技术生成

运行阶段类型识别RTTI(Runtime Type Identification)


    RTTI旨在为程序在运行阶段确定对象的类型提供一种标准方式。

 

    RTTI 只适用于包含虚函数的类。

 

RTTI的工作原理

C++有3个支持RTTI的元素:
(1) 如果可能的话,dynameic_cast操作符将使用一个指向基类的指针来生成一个指向派生类的指针;否则,该操作符返回0 —— 空指针。
(2) typeid操作符返回一个指出对象的类型的值。
(3) type_info结构存储了有关特定类型的信息。

 

    只能将RTTI用于包含虚函数的类层次结构,因为只有对于这种层次结构,才应该将派生对象的地址赋给基类指针。

 

1. dynameic_cast 操作符
    该操作符不能回答“指针指向的是哪类对象”这样的问题,但能够回答“是否可以安全地将对象的地址赋给特定类型的指针”这样的问题。

 

假设有如下类层次结构:
class Grand { // has virtual methods };
class Superb: public Grand { ... };
class Magnificent: public Superb { ... };


创建下面的指针:
Grand * pg = new Grand;
Grand * ps = new Superb;
Grand * pm = new Magnificent;

 

对于下面的类型转换:
Magnificent * p1 = (Magnificent *)pm;   // #1
Magnificent * p2 = (Magnificent *)pg;   // #2
Superb * p3 = (Magnificent *)pm;        // #3

 

类型转换#2就是不安全的,因为它将基类对象的地址赋给派生类指针。因此,程序将期望基类对象有派生来的特征,而通常这是不可能的。
类型转换#3是安全的,因为公有派生确保Magnificent对象同时也是一个Superb对象(直接基类)和一个Grand对象(间接基类)。虚函数确保了类方法调用的正确性。

 

dynameic_cast操作符的用法如下,其中pg指向一个对象:

 

Superb * pm = dynameic_cast<Superb *>(pg);

 

这提出了这样的问题:指针pg的类型是否可被安全地转换为Superb *? 如果可以,操作符将返回对象的地址,否则返回一个空指针。

 

    即使编译器支持RTTI,在默认情况下,它也可能关闭该特性。如果该特性被关闭,程序可能仍能够通过编译,但将出现运行阶段错误。例如,在Microsoft Visual C++ 7.1中,选择Project/proj properties(其中proj是当前使用的工程名),切换到选项卡C/C++,然后单击Language,将Enable Run-Time Type Info设置为Yes。

 

    应尽可能使用虚函数,而只在必要时使用RTTI。

 

    将dynameic_cast用于引用时,没有与空指针对应的引用值,因此无法使用特殊的引用值来指示失败。当请求不正确时,dynameic_cast将引发类型为bad_cast的异常,该异常是从exception类派生而来的,它是在头文件typeinfo中定义的。

 

可以像下面这样使用该操作符,其中rg是对Grand对象的引用:

#include <typeinfo>   // for bad_cast
...
try {
    Superb & rs = dynameic_cast<Superb &>(rg);
    ...
}
catch(bad_cast & ex) { ... }

 

2. typeid 操作符和 type_info 类
   typeid操作符使得能够确定两个对象是否为同种类型。它与sizeof有些相像,可以接受两种参数:
(1) 类名。
(2) 结果为对象的表达式。

 

   typeid操作符返回一个对type_info对象的引用,其中,type_info是在头文件typeinfo(以前为typeinfo.h)中定义的一个类。type_info类重载了==和!=操作符,以便可以使用这些操作符来对类型进行比较。

 

例如,如果pg指向的是一个Magnificent对象,则表达式:
typeid(Magnificent) == typeid(*pg)


结果将为bool值true,否则为false。

如果pg是一个空指针,程序将引发bad_typeid异常。该异常类型是从exception类派生而来的。在头文件typeinfo中声明的。

 

    type_info类的实现随厂商而异,但包含一个name()成员,该函数返回一个字符串(内容随实现而异,但通常是类的名称)。例如:

cout <<"Now processing type " << typeid(*pg).name()<<"./n";
将显示为指针pg指向的对象所属的类定义的字符串。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值