C++ RTTI

来源:互联网 发布:淘宝网之女款坡跟短靴 编辑:程序博客网 时间:2024/05/29 12:17

一,RTTI(Runtime  Type  Identification)的用途

假设有一个类层次结构,其中的类都是从同一个基类派生而来的,则可以让基类指针指向其中任何一个类的对象。这样便可以调用这样一个函数:在处理一些信息后,选择一个类,并创建这种类型的对象,然后返回它的地址,而该地址可以被赋为基类指针。如何知道指针指向的是哪种类型的对象呢?

在回答这个问题之前,先考虑为何要知道类型。可能希望调用类方法的正确版本,在这种情况下,这要该函数是类层次结构中所有成员都拥有的虚函数,则并不真正需要知道对象的类型。但派生类可能包含不是派生而来的方法,在这种情况下,只有某些类型的对象可以使用该方法。对于这种情况,RTTI提供了解决方案。

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


二,RTTI的工作原理

C++ 有三个支持RTTI的元素

a,dynamic_cast

1,dynamic_cast的作用与语法

dynamic_cast运算符将使用一个指向基类的指针来生成一个指向派生类的指针,用来执行"安全向下类型转换",也就是用来决定某对象是否属于某继承体系中的某个类。通常,想知道类型的原因在于:知道类型后,就可以知道调用特定的方法是否安全。例如,有下面的类继承体系:

class Grand{...};class Superb : public Grand{...};class Magnificent : public Superb{...};
首先,看下dynamic_cast的语法。该运算符的用法如下,其中pg指向某个对象:

Superb *pb = dynamic_cast<Superb *>(pg);
这提出了这样的问题:指针pg的类型是否可以安全地转换为Superb *?如果可以,运算符将返回对象的地址,否则返回一个空指针。通常,如果指向的对象(*pt)的类型为Type或者是从Type直接或间接派生而来的类型,则下面的表达式将指针(*pt)转换为Type类型的指针。

dynamic_cast<Type *>(pt);


2,使用dynamic_cast来检查是否可以进行安全类型转换

class Grand{public:    virtual void speak(){        cout<<"Grand Speak"<<endl;    }};class Superb : public Grand{public:    virtual void speak(){        cout<<"Superb Speak"<<endl;    }    virtual void say(){        cout<<"Superb say"<<endl;    }};class Magnificent : public Superb{public:    void speak(){        cout<<"Magnificent Speak"<<endl;    }    void say(){        cout<<"Magnificent say"<<endl;    }};

上面定义了三个类,Grand、Superb、Magnificent。Grand类定义了虚函数speak(),而其它的类都继承了该虚函数。Superb类定义了一个虚函数say(),而Magnificent也重新定义了它。程序定义了getOne()函数,该函数随机创建这三种类中某个类的对象。然后将对象的地址作为Grand*指针返回,循环将返回的指针赋给Grand*变量pg,然后使用pg调用speak()函数。因为这个函数是虚函数,所以代码能够正确调用指向的对象的speak()版本。如下:

Grand *pg;for(int i = 0; i < 5; i ++){    pg = getOne();    pg->speak();}
但是不能用相同的方式来调用say()函数,因为Grand类没有定义say()函数。然而,可以使用dynamic_cast运算符来检测是否可以安全地将pg转换为Superb类型指针。如果pg指向的对象的实际类型为Superb或Magnificent,则可以安全类型转换。在这两种情况下,都可以安全调用say()函数。
Grand *pg;Superb *ps;for(int i = 0; i < 5; i ++){    pg = getOne();    if(ps = dynamic_cast<Superb *>(pg)){        ps->say();    }}


b,typeid

1,typeid运算符的语法与作用

typeid运算符能够确定两个对象是否是同种类型。它接受两个参数,一是类名,二是结果为对象的表达式。typeid运算符返回一个type_info对象的引用,其中type_info是在头文件typeinfo中定义的一个类。type_info类重载了==和!=运算符,以便于使用这些运算符对类型进行比较。


2,typeid运算符的使用

typeid(Magnificent) == typeid(*pg);
如果pg指向的是一个Magnificent对象,则上面表达式的结果为true,否则为false。如果pg是一个空指针,程序将引发bad_typeid异常。


c,type_info

1,type_info的语法与作用

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


2,type_info的使用

cout<<typeid(*pg).name()<<endl;
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 社保这个月没扣怎么办 员工不交社保怎么办 公司没交社保怎么办 微信转账受限怎么办 支付宝违规限制怎么办 微信转账不还钱怎么办 碳放久了不爱起火怎么办 闻碳火时间久了怎么办 被代运营诈骗怎么办 被上海聚连骗了怎么办? 蓝领贷逾期半年怎么办 淘宝店倒闭售后怎么办 淘宝店铺宝贝被下架怎么办 医院被托管编制怎么办 领码分百万账号异常怎么办 拼多多帐号异常怎么办 qq钱包交易异常怎么办 托管公司跑了怎么办? 花呗退款没到账怎么办 车辆过户了车牌怎么办 货车资格证脱审怎么办 廉租房夫妻离婚怎么办 二手车行驶证怎么办的? 卖二手车后车牌怎么办 房子动迁没过户怎么办? 北京买车指标怎么办 签合同不交社保怎么办 养老保险交重了怎么办 公司克扣员工工资应该怎么办 天猫拒绝退款怎么办 一看书就犯困怎么办 擦了风油精过敏怎么办 擦了清凉油过敏怎么办 脸上擦风油精过敏怎么办 搽了风油精过敏怎么办 背带裤显屁股大怎么办 打底衫肥了怎么办 天猫卖家总是发信息怎么办 房子装修完有味怎么办 房子装修油漆味怎么办 房子装修代款怎么办