程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 從RTTI談C++的向下轉型

從RTTI談C++的向下轉型

編輯:關於C語言
 

1.什麼是RTTI?

RTTI 是“Runtime Type Information”的縮寫,意思是:運行時類型信息。它提供了運行時確定對象類型的方法。允許“用指向基類的指針或引用來操縱對象”的程序能夠獲取到“這些指針或引用所指對象”的實際派生類型。在 c++中,為了支持 RTTI 提供了兩個操作符 : 
    1 dynamic_cast 操作符:它允許在運行時刻進行類型轉換,從而使程序能夠在一個類層次結構中安全地轉換類型(安全的向下轉型)。把基類指針轉換成派生類指針,或把指向基類的左值轉換成派生類的引用。當然只有在保證轉換能夠成功的情況下才可以;  
    2 typeid操作符:它指出指針或引用指向的對象的實際派生類型。  
    但是,對於要獲得的派生類類型的信息,dynamic_cast 和 typeid操作符的操作數的類型必須是帶有一個或多個虛擬函數的類類型,即對於帶有虛擬函數的類而言,RTTI 操作符是運行時刻的事件,而對於其他類而言,它只是編譯時刻的事件。

2. RTTI如何實現

     C++的RTTI是最簡單的,只能獲得類名和相關的繼承信息;而VB、Delphi、Java等確復雜得多,甚至於支持屬性名、方法名、事件名等。


 

如圖,C++使用type_info類的對象保存每個對象的相關信息如對象名稱、對象類型等。而所謂RTTI就是在執行期取得對象的type_info。所以C++采用了和虛函數同樣的辦法,使用vtable(通常為第一個slot)保存需要執行期獲得type_info的對象的type_info對象地址。那麼由pt指向的class object的type_info可在執行期通過如下方式獲得:

(type_info)*(type_info*)(pt->vptr[0]);

通過上述實現分析我們也可以知道,C++的RTTI只能用於那些展現“多態”(內含虛函數)的類型有效。因為只有這樣的類才有vtable。

3. 向下轉型

    將一個Base class對象的指針轉為Derived class對象的指針或將Base class的左值轉為Derived class的引用稱為向下轉型。

注:不能講Base class的對象轉為Derived class的對象(除非定義相應轉換操作符)。如下語句是錯誤的:

Base bobj;

Derived dobj=static_cast<Derived>(bobj) ;//error,

Derived dobj=(Derived)(bobj) ;//error

但如下語句是正確的:

Derived dobj;

Base bobj=(Base)dobj;//正確,造成對象切割

Base bobj=static_cast<Base>(dobj);//正確,造成對象切割

 

向下轉型示例:

(1) 基類指針轉為子類指針

    Base bobj;

    Base *pb=&bobj;

    Derived *pd=(Derived*)pb;//方式一

Derived *pd=static_cast<Derived*>(pb);//方式二

   Derived *pd=dynamic_cast<Derived*>(pb);//方式三,只有Base class中有虛函數才能使用,否則編譯錯誤(Derived class中有虛函數也不行)

(2) 基類左值轉子類引用

    Base bobj;

Derived dobj;

Derived &dref=(Derived&)(bobj);//方式一

Derived &dref=static_cast<Derived&>(bobj);//方式二

Derived &dref=dynamic_cast<Derived&>(bobj);//方式三,只有Base class中有虛函數才能使用,否則編譯錯誤(Derived class中有虛函數也不行)

(3) 基類左值轉子類引用

   Derived dobj;

Base& bref=dobj;

Derived &dref=(Derived&)(bref);

Derived &dref=static_cast<Derived&>(bref);

Derived &dref=dynamic_cast<Derived&>(bref);

 

向下轉型的隱患

向下轉型有著潛在的危險,因為當基類指針指向的是基類對象,而將基類指針轉為子類指針時,如果通過轉換後的子類指針訪問子類的專有成員,就會造成內存錯誤,因為實際指向的是基類對象,而基類對象中不存在這些成員。(引用轉換類似)  

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved