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操作一個null 指標
------------------------------其它文法-----------------------------------
static_cast : 為了“行為良好”和“行為較好”而使用的映射,包括一些我們可能現在不用的映射(如向上映射和自動類型轉換)。
const_cast :用於映射常量和變數(const和volatile)
reinterpret_cast:為了映射到一個完全不同的意思。這是所有映射中最危險的。