4-1運行時類型識別RTTI
[TOC]
1.RTTI
? Run-Time Type Identification
? 運行時類型識別
- 使程序能夠獲取由基指針或引用所指向的對象的實際派生類型,即允許“用指向基類的指針或引用來操作對象”的程序能夠獲取到“這些指針或引用所指對象”的實際派生類型。
2.操作符typeid
? 等同于sizeof這類的操作符。
? 返回結果是名為type_info的標準庫類型的對象的引用。
? 頭文件typeinfo
- 它的表達式有下圖兩種形式:
NAME | TYPEID | TYPE |
---|---|---|
typeid | 類型ID | typeid(type) |
typeid | 運行時刻類型ID | typeid(expr) |
// type_info類的源碼
class type_info {
public:
const char *name() const;
bool operator==(const type_info& rhs) const;
bool operator!=(const type_info& rhs) const;
int before(const type_info& rhs) const;
virtual ~type_info();
private:
......
};
typeid使用注意事項
Ⅰ typeid返回一個type_info對象的引用;
Ⅱ 如果想通過基類的指針獲得派生類的數據類型,基類必須帶有虛函數;
Ⅲ 只能獲取對象的實際類型。
3.操作符dynamic_cast
- 允許運行時刻進行類型轉換,從而使程序能夠在一個類層次結構中安全地轉化類型。
dynamic_cast使用注意事項
Ⅰ 只能應用于指針和引用的轉換;
Ⅱ 要轉換的類型中必須包換虛函數;
Ⅲ 轉換成功返回派生類的地址,失敗返回NULL。
4.代碼示例
// 鳥類和飛機類都會“降落”和“起飛”,因此“降落”和“起飛”的特性寫入一個接口類中
// 鳥類會“覓食”,并繼承接口類的“降落”和“起飛”
// 飛機類會“負重”,并繼承接口類的“降落”和“起飛”
// 傳入一個基類指針,調用對象的“降落”和“起飛”。并根據對象的類型的不同,分別調用各自的“覓食”或“負重”
void doSomething(Flyable *obj) {
obj->takeoff();
cout << typeid(*obj).name() << endl;
if(typeid(*obj) == typeid(Bird)) {
Bird *bird = dynamic_cast<Bird *>(obj);
bird->foraging(); // 如果是Bird,則覓食
}
if(typeid(*obj) == typeid(Plane)) {
Plane *plane = dynamic_cast<Plane *>(obj);
plane->carry(); // 如果是Plane,則負重
}
obj->land();
}