RTTI的兩種使用方法:
1. 第一種是typeid(),它很像sizeof,看上去像一個函數,但實際上它是由編譯器實現的。
typeid()的參數是一個對象引用或者指針,返回全局typeinfo類的常量對象的一個引用。可以用==或者!=來互相比較這些對象。
ISO C++標准並沒有確切定義typeinfo,它的確切定義編譯器相關的,但是標准卻規定了其實現必需提供如下四種操作:
typeinfo1 == typeinfo2 | 如果兩個對象typeinfo1和typeinfo2類型相同,則返回true;否則返回false |
typeinfo1 != typeinfo2 | 如果兩個對象typeinfo1和typeinfo2類型不同,則返回true;否則返回false |
typeinfo.name() | 可以使用name()來獲得類型的名稱。例如:cout << typeid(*s).name() |
typeinfo1.before(t2) | 可以使用before(typeinfo&)來查詢一個typeinfo對象是否在另一個typeinfo對象的前面(按照繼承順序 |
當typeid操作符的操作數是不帶有虛函數的類類型時,typeid操作符會指出操作數的類型,而不是底層對象的類型。
如果typeid操作符的操作數是至少包含一個虛擬函數的類類型時,並且該表達式是一個基類的應用,則typeid操作符指出底層對象的派生類類型。
typeid可以運用於非多態類型,但這種方法獲得的信息是值得懷疑的。
2. 第二種是“dynamic_cast安全類型向下映射”
可以使用C++的靜態映射static_cast強制執行,但這樣做很危險,因為沒有辦法明確地知道它實際上是什么。
所以使用dynamic_cast
shape* sp = new circle;
circle* cp = dynamic_cast<circle*>(sp);
if (cp) cout << "cas successful"; // 如果返回一個地址,成功;返回null,說明它不是一個circle* 對象。
動態映射不僅可以用來確定准確的類型,也可用於多層次繼承關系中的中間類型。
typeid總是產生一個typeinfo對象的引用來描述一個對象的准確類型,因此它不會給出中間層次的信息。
typeid看到的指針類型是基類,而它看到的引用類型則是派生類。
typeid看到的指針指向的類型是派生類,而它看到的引用的地址類型則是基類。
多重繼承的時候,如果將一個實際指向子類的基類指針做強制轉換成子類指針也會出錯。
------------------------------兩種Bad-cast-----------------------------------
1. dynamic_cast轉換一個完全不相關的類
2. typeid操作一個空指針
------------------------------其它語法-----------------------------------
static_cast : 為了“行為良好”和“行為較好”而使用的映射,包括一些我們可能現在不用的映射(如向上映射和自動類型轉換)。
const_cast :用於映射常量和變量(const和volatile)
reinterpret_cast:為了映射到一個完全不同的意思。這是所有映射中最危險的。