天天看點

C++ typeid關鍵字詳解 typeid關鍵字 RTTI(Run-Time Type Identification)-運作時類型識别 實作機制與使用技巧

注意:typeid是操作符,不是函數。這點與sizeof類似)

運作時獲知變量類型名稱,可以使用 typeid(變量).name()

需要注意不是所有編譯器都輸出”int”、”float”等之類的名稱,對于這類的編譯器可以這樣使用

在揭開typeid神秘面紗之前,我們先來了解一下rtti(run-time type identification,運作時類型識别),它使程式能夠擷取由基指針或引用所指向的對象的實際派生類型,即允許“用指向基類的指針或引用來操作對象”的程式能夠擷取到“這些指針或引用所指對象”的實際派生類型。

在c++中,為了支援rtti提供了兩個操作符:<code>dynamic_cast</code>和<code>typeid</code>

dynamic_cast允許運作時刻進行類型轉換,進而使程式能夠在一個類層次結構中安全地轉化類型,與之相對應的還有一個非安全的轉換操作符static_cast,因為這不是本文的讨論重點,是以這裡不再詳述,感興趣的可以自行查閱資料。

typeid是c++的關鍵字之一,等同于sizeof這類的操作符。typeid操作符的傳回結果是名為type_info的标準庫類型的對象的引用(在頭檔案typeinfo中定義,稍後我們看一下vs和gcc庫裡面的源碼),它的表達式有下圖兩種形式。

如果表達式的類型是類類型且至少包含有一個虛函數,則typeid操作符傳回表達式的動态類型,需要在運作時計算;

否則,typeid操作符傳回表達式的靜态類型,在編譯時就可以計算。

iso c++标準并沒有确切定義<code>type_info</code>,它的确切定義編譯器相關的,但是标準卻規定了其實作必需提供如下四種操作(在之後的章節中我會來分析type_info類檔案的源碼)

運算

描述

t1 == t2

如果兩個對象t1和t2類型相同,則傳回true;否則傳回false

t1 != t2

如果兩個對象t1和t2類型不同,則傳回true;否則傳回false

t.name()

傳回類型的c-style字元串,類型名字用系統相關的方法産生1

t1.before(t2)

傳回指出t1是否出現在t2之前的bool值

type_info類提供了public虛 析構函數,以使使用者能夠用其作為基類。它的預設構造函數和拷貝構造函數及指派操作符都定義為private,是以不能定義或複制type_info類型的對象。程式中建立type_info對象的唯一方法是使用typeid操作符(由此可見,如果把typeid看作函數的話,其應該是type_info的 友元)。type_info的name成員函數傳回c-style的字元串,用來表示相應的類型名,但務必注意這個傳回的類型名與程式中使用的相應類型名并不一定一緻(往往如此,見後面的程式),這具體由編譯器的實作所決定的,标準隻要求實作為每個類型傳回唯一的字元串。

使用<code>sudo find / -name typeinfo.h</code>來查找源碼

C++ typeid關鍵字詳解 typeid關鍵字 RTTI(Run-Time Type Identification)-運作時類型識别 實作機制與使用技巧

下表列出了使用typeid操作符的表達式的值

typeid(a) == typeid(int)

true

typeid(a) == typeid(float)

false

typeid(a) == typeid(int *)

typeid(b) == typeid(double)

typeid(b) == typeid(float)

typeid(b) == typeid(long double)

typeid(c) == typeid(char *)

typeid(c) == typeid(char)

typeid(c) == typeid(string)

typeid(d) == typeid(long)

typeid(d) == typeid(int)

操作符typeid傳回的是一個type_info類(用于描述資料類型的一個系統類)對象的引用。這個操作符可以用于表達式和類型名(包括自定的資料類型,比如類)。

假設我們根據例2中定義的兩個類來定義如下指針:

下表将給出使用typeid操作符的結果。

typeid(p) == typeid(base*)

typeid(p) == typeid(derived*)

typeid(*p) == typeid(base)

typeid(*p) == typeid(derived)

對于表達式typeid(p),同樣,因為p是base*類型的指針,是以typeid(p) == typeid(base*)為真,而typeid(p) == typeid(derived*)為假。而對于表達式typeid(*p),由于此時的基類不具有多态性,因而*p将會采用編譯期類型來計算,編譯期*p是base對象,是以表達式typeid(*p) == typeid(derived)為假,typeid(*p) == typeid(base)為真。

假設我們如本例所示定義了兩個類base類和derived類,基于這兩個類定義,我們定義指針如下:

對于表達式typeid(p),因為p是base*類型的指針,是以typeid(p) == typeid(base*)為真,而typeid(p) == typeid(derived*)為假。而對于表達式typeid(*p),因為base類具有多态性,因而在計算typeid(*p)時會根據運作時p所指向的實際類型去計算,而本例中p指向的是派生類對象,是以表達式typeid(*p) == typeid(derived)為真,typeid(*p) == typeid(base)為假。

C++ typeid關鍵字詳解 typeid關鍵字 RTTI(Run-Time Type Identification)-運作時類型識别 實作機制與使用技巧
轉載:http://blog.csdn.net/gatieme/article/details/50947821

繼續閱讀