【RTTI】C++运行时类型鉴定机制


Run-Time Type Identification
每个类都拥有一份what_am_i()函数,都返回一个足以代表该类的字符串:

class Fibonacci : public num_sequence         

{

public:
        virtual const char* what_am_i() const ( return "Fibonacci";}

};


另一种设计手法,便是只提供唯一的一份what_am_i(),令各派生类通过继承机制加以复用。这种设计手法可使各派生类不必再提供各自的what_am_i()。
这种设计的一种可能做法,就是为num_sequence增加一个atring member,并令每一个派生类的constructor都将自己的类名作为参数,传给num_sequence的constructor。例如:


inline Fibonacci::
Fibonacci( int len, int beg_pos )
: num_sequence ( len, beg_pos, _elems, "Fibonacci"){}


另一种实现便是利用所谓的typeid运算符,这是所谓运行时类型鉴定机制(Run-Time Type Identification,RTTI)的一部分,由程序语言支持。它让我们得以查询多态化的class pointer或class reference,获得其所指对象的实际类型。


#include <typeinfo>
inline const char* num sequence:: what_am_i() const
{ return typeid( *this ).name();}


使用typeid运算符之前,必须先包含头文件typeinfo。typeid 运算符会返回一个type_info对象,其中储存着与类型相关的种种信息。每一个多态类(polymorphic class ),如Fibonacci、Pell,等等,都对应一个type_info对象,该对象的name()函数会返回一个const char*,用以表示类名。 who_am_i()函数中的表达式


typeid( *this )


会返回一个 type_info对象,关联至“who_am_i()函数之中由this指针所指对象”的实际类型。

type_infoclass也支持相等和不等两个比较操作。例如,以下程序代码可以决定ps是否指向某个 Fibonacci对象:


num_sequence *ps = &fib;
if( typeid(*ps) ==typeid( Fibonacci))
// ok,ps的确指向某个Fibonacci对象

如果接下来我们这么写:

ps->gen_elems( 64 );


我们就可预期调用的是Fibonacci的gen_elems()。然而,虽然我们从这个检验操作中知道ps的确指向某个Fibonacci对象,但直接在此通过ps调用Fibonacci的gen_elems()函数,却会产生编译错误:


//错误:因为ps并非一个Fibonacci指针--虽然我们知道,
//    它现在的确指向某个Fibonacci对象!    
ps->Fibonacci::gen_elems( 64 );


是的,ps并不“知道”它所指向的对象实际上是什么类型一纵使我们知道,typeid及虚函数机制也知道。


为了调用 Fibonacci 所定义的gen_elems(),我们必须指示编译器,将ps的类型转换为 Fibonacci 指针。static_cast运算符可以担起这项任务;


if( typeid( *ps) ==typeid( Fibonacci))
Fibonacci *pf = static_cast<Fibonacci*>( ps); //无条件转换

pf->gen_elems( 64 );


static_cast 其实有潜在危险,因为编译器无法确认我们所进行的转换操作是否完全正确。这也就是我要把它安排在“typeid运算符的运算结果为真”的条件下的原因。dynamic_cast运算符就不同,它提供有条件的转换:


if( Fibonacci *pf = dynamic_cast<Fibonacci*>( ps))
pf->gen_elems( 64 );


dynamic_cast 也是一个RTTI运算符,它会进行运行时检验操作,检验ps所指对象是否属于 Fibonacci类。如果是,转换操作便会发生,于是pf便指向该Fibonacci对象。如果不是,dynamic_cast运算符返回 0。一旦if语句中的条件不成立,那么对Fibonacci的gen_elems()所进行的静态调用操作也不会发生。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值