RTTI(運行時類型識別)


  運行時類型識別(Run-time type identification , RTTI),是指在只有一個指向基類的指針或引用時,確定所指對象的准確類型的操作。其常被說成是C++的四大擴展之一(其他三個為異常、模板和名字空間)。

使用RTTI的兩種方法:

  1、typeid()

  第一種就像sizeof(),它看上像一個函數,但實際上它是由編譯器實現的。typeid()帶有一個參數,它可以是一個對象引用或指針,返回全局typeinfo類的常量對象的一個引用。可以用運算符“= =”和“!=”來互相比較這些對象,也可以用name()來獲得類型的名稱。如果想知道一個指針所指對象的精確類型,我們必須逆向引用這個指針。比如:

#include <typeinfo>
#include <iostream>
#include <cmath>
using namespace std;
class Shape
{
public :
    int area(float r)
    {
        float s=3.14*pow(r,2);
        return s;
    }
};
int main()
{  
    Shape* shape=new Shape;
    cout<< typeid(*shape).name()<<endl;
    system("pause");
}

  運行結果為:

  為了保持一致性,typeid()也可以用於內部類型,所以下面的表達式結果為true:

typeid(36) == typeid(int)
typeid(0) == typeid(int)

int i;
typeid(i) == typeid(int)
typeid(&i) ==typeid(int*)

  可以用typeid 檢查基本類型和非多態類型

//可以用typeid 檢查基本類型和非多態類型: 
#include <typeinfo>
#include <iostream>
using namespace std;
typedef  unsigned int UINT ;
int main()
{  
    cout<< typeid(UINT).name()<<endl;
    cout<< typeid(string).name()<<endl;
    system("pause");
}

  運行結果如圖所示:

  用typeid分析指針與引用的區別

#include <typeinfo>
#include <iostream>
using namespace std;
class B
{   
public:  
    virtual double fun() 
    { 
        return 0.1; 
    }   
};
class D :public B   
{
};
int main()
{   
    B *p = new D;    
    B &r = *p;    //無名對象照樣有別名
    cout<<(typeid(p)==typeid(B*)); //僅指向子類中父類部分
    cout<<(typeid(p)!=typeid(D*));  //而非指向整個子類對象
    cout<<(typeid(r)==typeid(D));   //引用的類型卻是子類的
    cout<<(typeid(*p)==typeid(D)); //間址訪問的是子類對象
    cout<<(typeid(*p)!=typeid(B));  //而非父類
    cout<<(typeid(&r)==typeid(B*)); //引用的地址是父類的
    cout<<(typeid(&r)!=typeid(D*));  //而非子類的
    system("pause");
    return 0;
}

  運行結果:

  2、dynamic_cast <type-id> (expression)

  該運算符把expression轉換成type-id類型的對象。 Type-id 必須是類的指針、類的引用或者void*,不可是對象;如果 type-id 是類指針類型,那么expression也必須是一個指針,如果 type-id 是一個引用,那么 expression 也必須是一個引用。
  dynamic_cast主要用於類層次間的 上行轉換下行轉換,還可以用於類之間的 交叉轉換。在類層次間進行上行轉換時, dynamic_caststatic_cast的效果是一樣的;在進行下行轉換時,dynamic_cast具有類型檢查的功能,比static_cast更安全。
#include <typeinfo>
#include <iostream>
using namespace std;
class Shape
{
public:
    virtual void Draw()
    {
    }
};
class Circle:public Shape
{
public:
    virtual void Draw()
    {
    }
};
int main()
{  
    Shape* sp=new Circle;
    Circle* cp=dynamic_cast<Circle*>(sp);
    if(cp)  
        cout<<"cast successful"<<endl;;
    system("pause");
}

  運行結果:

如何使用RTTI:

  • 先激活RTTI;
  • 對象所屬類型必須是多態類族
  • 若使用dynamic_cast<>轉換一個引用,則要使用異常處理機制,因為它可能拋出 std::bad_cast異常;當使用dynamic_cast<>運算符轉換一個指針時,定要檢查結果是否為NULL
  • 若使用typeid (*p)來檢索對象的類型信息,又恰碰 p == NULL時,將拋出std::bad_typeid異常;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM