RTTI(Runtime Type Identification)

  所谓的RTTI是指在执行的同时判断某个object或某一个pointer属于何种类型,它是C++许多高级技术依领域的基础。RTTI的主要形式在C++中是以typeid和dynamic_cast operator展现。

一、typeid operator

  typeid operator 换语法如下:

typeid( type-id)     #例如:typeid(CPoint)
typeid(expression)   #例如:typeid(pPoint)或typeid(*pPoint)

  typeis()可以在程序执行期间决定一个object的类型(type)。它的回传值是一个const type_info&。C++ Standard中对于type_info object定义如下:

class type_info{
public:
    virtual ~type_info();
    bool operator==(const type_info& )const;
    bool operator!=(const type_info& )const;
    bool before(const type_info& )const;
    const char*name()const; //传回class 原始名称
private:
    //prevent memberwise init  and copy
    type_info(const type_info& );
    type_info& operator=(const type_info& );
    //data members
};

  有些文献曾提出以编码后的文字来代替实际的class名称,可能会获得比较好的执行效率。visual C++就是这么做的,在其 \msdev\include\typeinfo.h 中对class type_info 定义如下:

// declared in typeinfo.h
class type_info {
public:
    _CRTIMP virtual ~type_info(); 
    _CRTIMP int operator==(const type_info& rhs) const;
    _CRTIMP int operator!=(const type_info& rhs) const;
    _CRTIMP int before(const type_info& rhs) const;
    _CRTIMP const char* name() const;
    _CRTIMP const char* raw_name() const;
private:
    void *_m_data;
    char _m_d_name[1];
    type_info(const type_info& rhs);
    type_info& operator=(const type_info& rhs);
};

  我们可以利用其中的name()和rawname()两个member functions,取出我们所探询之object的类形名称。name()传回的指针,指向一个人类可读的字串,rawname()传回的指针则指向一个编码后的字串,非人类可读形式。此一编码后的字串对于两个类形之间的比对更有效率。

  如果你要使用typeid(),程序中必须导入typeinfo.h,下面是个实际的例子:

#include<iostream.h>
#include<typeinfo.h>

class B //base class ,non-polymorphic
{
 public:
    int _data1;
};

class D :public B //derived class ,non-polymorphic too.
{
  public:
        int _data2;
};

void main()
{
    B *pb = new B;
    D *pd = new D;
    cout<<" B is Base type, D is Derived type" <<endl; 
 //check object pointer's type
    if (typeid(B)==typeid(*pb))
        cout<<"pb is B type"<<endl;
    else
        cout <<"pb is not B type" <<endl;
    if (typeid(D)==typeid(*pd))
        cout<<"pd is D type"<<endl;
    else
        cout <<"pd is not D type" <<endl;
 //check object pointer's type name
     cout << "pb's type name = " << typeid(pb).name() << endl;
     cout << "pd's type name = " << typeid(pd).name() << endl;
     cout << "pb's type rawname = "<< typeid(pb).raw_name() << endl;
     cout << "pd's type rawname = "<< typeid(pd).raw_name() << endl;
// check object's type name
     cout << "*pb's type name = " << typeid(*pb).name() << endl;
     cout << "*pd's type name = " << typeid(*pd).name() << endl;
     cout << "*pb's type rawname = "<< typeid(*pb).raw_name() << endl;
     cout << "*pd's type rawname = "<< typeid(*pd).raw_name() << endl;
     if (typeid(pb).before(typeid(pd)))
         cout << "pb before pd" << endl;
     else
         cout << "pb not before pd" << endl;
 // check objects' relationship
    if (typeid(*pb).before(typeid(*pd)))
          cout << "*pb before *pd" << endl;
    else
          cout << "*pb not before *pd" << endl;
    B *pb1 = new D; // base ptr point to derived object.
    cout << "pb1's type name = " << typeid(pb1).name() << endl;
    cout << "*pb1's type name = " << typeid(*pb1).name() << endl;
// check objects' relationship
    if (typeid(*pb1).before(typeid(B)))
          cout << "*pb1 before B" << endl;
    else
          cout << "*pb1 not before B" << endl;
    if (typeid(*pb1).before(typeid(D)))
          cout << "*pb1 before D" << endl;
    else
          cout << "*pb1 not before D" << endl;
}
     

 

  程序执行结果:

B is Base type, D is Derived type
pb is B type
pd is D type
pb's type name = class B * // 原名称
pd's type name = class D * // 原名称
pb's type rawname = .PAVB@@ // 编码后的名称
pd's type rawname = .PAVD@@ // 编码后的名称
*pb's type name = class B // 原名称
*pd's type name = class D // 原名称
*pb's type rawname = .?AVB@@ // 编码后的名称
*pd's type rawname = .?AVD@@ // 编码后的名称
pb before pd // before 的意思是在 classes hierarchy 的更高层
*pb before *pd
pb1's type name = class B * // 合理
*pb1's type name = class B // 想不到吧!
*pb1 not before B // 合理
*pb1 before D // 想不到吧!

  请注意,虽然pb1指向一个真正的class D object,但利用typeid()所得到的检查结果却显示,pb1所指类的type name 是“class B”,想不到吧!如果我把typeid()应用于polymorphic classes身上,执行结果会出现一点变化,现在将前一个例子做一些修改:

// building : cl -GR typeid.cpp
#include <iostream.h>
#include <typeinfo.h>

class B // base class, polymorphic.
 {
   public:
       virtual void func() { };
       int _data1;
};

class D : public B // derived class, polymorphic too.
{
   public:
       virtual void func() { };
       int _data2;
 };

   现在让我们看一下执行结果,变化出现在polymorphism发生时,也就是当程序码以base type pointer 指向derived type object时:

             B* pb1 = new D; // base ptr point to derived object.

        此行之后的执行结果如下:

           pb1's type name = class B * // 合理
          *pb1's type name = class D // 好极了!
          *pb1 not before B // 合理
          *pb1 not before D // 合理
 

         在polymorphism情况下,虚拟机制确实记录了pb1所指类的类型为“classD”,虽然pb1本身的原始类型为“class B” ,这种能力为我们带来许多好处。

      

posted on 2024-09-08 07:43  阮春义  阅读(0)  评论(0编辑  收藏  举报

导航