1. 程式人生 > >【C/C++學習】之十四、RTTI

【C/C++學習】之十四、RTTI

RTTI(Runtime TypeIdentification)

提供了執行時確定物件型別及轉換指標或引用型別的方法。  有關內容包括類名稱,資料成員名稱與型別,函式名與型別等。

在大多數面向度地向專家傳播自己設計理念時,都主張在設計和開發中使用虛擬成員函式而不是使用RTTI機制,但是再很多情況下虛擬成員函式無法克服本身的侷限。每當涉及處理異類容器和根基類層次時,不可避免要對物件型別進行動態判斷,也就是動態型別的偵測。在C++中提供了兩個運算子typeid 和 dynamic_cast。

typeid   可以獲取與某個物件關聯的執行時型別資訊。他返回的是type_info型別,該型別描述型別資訊。

Typeid運算子用於獲得一個型別或者物件的執行時資訊,如下:

Typeid(type)

Typeid(object)

其中type可以是有虛擬函式的類型別,也可以是沒有虛擬函式的類型別

1、  有虛擬函式

A *a = new B;

Typeid(a)==typeid(A*);和typeid(*a)==typeid(A)  都返回true                                                                                                                         

2、  無虛擬函式

A *a = new B;

Typeid(a)==typeid(A*)和typeid(*a)==typeid(A)都返回true

Typeid是在typeinfo.h標頭檔案中,看下面程式碼

A *a = new B;

Cout << typeid(*a).name() <<endl;

Name函式可以獲得指標a指向的物件型別,因為指標a指向的是一個B型別的物件,多以執行的時候會輸出B。

如果a是NULL,那麼會丟擲bad_typeid異常。

Typeid和dynamic_cast區別:

1、  dynamic_cast運算子只能處理物件,而typeid運算子能夠以型別和物件作為運算元,其中物件可以使基本型別,包括整形,浮點型,char等

2、  typeid()和dynamic_cast<>()函式都是在執行時才能獲得型別資訊,而不是在靜態編譯時獲得。

3、  typeid()函式不是一個模板函式

4、  typeid()和dynamic_cast<>()函式接收基類指標或者引用,該指標或者引用可以指向一個派生類物件。

5、  typeid()函式返回類名,而dynamic_cast<>()函式被用來傳遞類名。

6、  使用typeid()函式能發現該物件的精確型別,但不能轉換該指標,dynamic_cast<>()函式能轉換該指標,但不能確定該物件的精確型別。

Dynamic_cast 

執行dynamic_cast運算子需要額外的執行時間,為了避免效能損耗通常使用static_cast運算子。   雖然使用static_cast運算子在速度上優於dynamic_cast運算子,但是static_cast運算子在用於向下轉型時可能存在危險並會導致錯誤。  如果一定要使用static_cast運算子,那麼就要確保向下轉型的安全性。

使用static_cast運算子並不能保證轉型的有效性,static_cast運算子僅僅執行需要的指標運算,為了確保使用static_cast運算子進行向下轉型是安全的,使用者必須對每次要執行的轉型都進行測試。如果使用dynamic_cast運算子就無需使用者測試,因為dynamic_cast運算子執行失敗時會返回空指標或丟擲異常。


要注意的是:

預設情況下,編譯器是關閉RTTI的,目的是消除效能上的開銷,如果程式中使用了RTTI,那麼編譯前要進行啟用RTTI。

最基本的RTTI包括:

1、  類識別:類名稱或ID

2、  繼承關係:支援執行時的向下轉換,即動態轉換

3、  物件結構:屬性的型別、名稱及其位置

4、  成員函式:函式的型別、名稱及其引數型別等

5、  能獲得類所例項化的各物件

RTTI常見的應用:   異常處理,動態轉換,多個檔案整合,物件IO

1、  異常處理:需要RTTI  例如類名稱等

2、  動態轉換:在類中,向下轉換需要類繼承的RTTI

3、  多個檔案整合:當某個程式中的物件需要使用另一個程式中的物件時,在一般的C++程式中,常見的解決方法是在原始碼中將需要的物件的類定義包含進來,在編譯時將當前檔案與其包含的檔案整合,但又無法再次重新編譯,因此只能依賴於RTTI。

4、  物件IO:C++將IO物件及與它相關的獨享所屬的類名稱等RTTI內容完整的儲存起來,讀取物件時可依賴這些RTTI內容為物件分配記憶體空間。

2012/10/14

jofranks 於南昌