RTTI【引】

来源:互联网 发布:小米账号删除同步数据 编辑:程序博客网 时间:2024/04/29 01:58

在C++中可以给基类的指针或者引用赋一个子类的对象,怎么知道这些基类的指针或者引用的实际类型呢?这就需要运行时类型识别(RTTI)。有两个操作符提供RTTI:typeid和dynamic_cast。对于带虚函数的类,运行时执行RTTI操作符,对于其它类型,编译时执行RTTI操作符。


1.dynamic_cast
基类的指针或者引用可能指向一个子类的对象,有时候想使用子类新增的函数而不是基类定义的共有的函数,这时候就需要通过dynamic_cast把这个指针或者引用转换成子类的指针或者引用。
对于指针:如果要转换的目标类型不是该指针指向的实际类型,则失败,返回为0.对于引用:失败时抛出一个bad_cast异常。

2.typeid操作符
有时候需要知道表达式到底是什么类型。比如,一个基类的指针或者引用,在运行时可能指向基类的对象,也可能指向子类的对象,那么在运行的某一时刻到底是哪个具体的类型呢?这样的问题可以通过typeid操作符来解决。
typeid(e); e可以为表达式,类的名称,或者类型的名称。
当e是定义了至少一个虚函数的类的对象时,才在运行时计算类型。
typeid操作符的结果是名为type_info的标准库类的对象引用。要使用type_info需要包含相应的头文件。
classname *p;
if(typeid(*p) == typeid(classname))
{...}

如果是typeid(p),那么Testing a pointer returns the static compile-time type of the pointer.没有测试,不知道type of the pointer的准确含义。

3.使用RTTI的一个例子(来自C++ primer)
任务:测试两个对象给定的数据成员集是否相等。子类可以增加数据,所以比较时应该考虑到这些增加的数据成员。
方案1:
bool operator == (const base&, const base&);
bool operator == (const base&, const derived&);
bool operator == (const derived&, const base&);
bool operator == (const derived&, const derived&);
两个类4个函数,3个类9个。。。这种方案不可行
可行的方案:
class base{
   friend bool operator == (const base&, const base&);
   protected:
      virtual bool equal (const base&) const;
}

class derived:{
   friend bool operator == (const base&, const base&);
   private:
      virtual bool equal (const base&) const;
}

bool operator == (const base& lhs, const base& rhs)
{
     return typeid(lhs) == typeid(rhs) && lhs.equal(rhs);
     //先比较是不是同一个类型,不是表达式直接返回false,
     //是同一类型,则调用equal,equal是一个虚函数,会根据lhs的类型调用相应的equal
     //如果调用子类的,那么要先把rhs动态转换一下
     //如果是基类的则不用
     //这种方法扩展性好,无论多少个子类,先用类型比较保证equal调用时,lhs和rhs的类型是一样的
     //所以equal中,只要把rhs动态转换成和lhs相同的类型,然后再比较即可
}

bool derived::equal(const base &rhs) const
{
   if(const derived * dp = dynamic_cast<const derived*> (&rhs))
   {...}
   else
      return false;
}

bool base::equal(const base & rhs) const
{
    ...
}

原创粉丝点击