RTTI(Run-Time Type Information,執行期類型資訊) 讓程式在執行期間能辨識物件的實際衍生類型。C++ 提供兩大核心運算子:
dynamic_cast:執行期安全向下轉型,失敗回傳 nullptr(指標)或拋出異常(引用)。typeid:回傳 std::type_info 參考,可比較類型名稱與繼承關係。前提條件:類別必須包含至少一個 virtual 函數(多態類別),否則 RTTI 僅在編譯期生效。
C++ 編譯器為每個多態類別建立 type_info 物件,儲存類別名稱、繼承關係等。虛函數表(vtable)的第一個槽位通常存放指向該 type_info 的指標。透過物件的 vptr 即可在執行期取得類型資訊:
type_info& info = *static_cast(obj->vptr)[0];
這也是為何只有多態類別(有虛函數)才支援 RTTI——非多態類別沒有 vtable,無法存放型別資訊。
將基類指標/引用轉為衍生類指標/引用稱為「向下轉型」。注意:無法直接將基類物件轉為衍生類物件(會造成物件切割),只能轉換指標或引用。
| 方式 | 語法 | 安全性 | 條件 |
|---|---|---|---|
| C 風格轉型 | (Derived*)basePtr | 不安全,無檢查 | 任意類別 |
| static_cast | static_cast | 不安全,無執行期檢查 | 任意類別 |
| dynamic_cast | dynamic_cast | 安全,執行期檢查 | 基類需有虛函數 |
class Base { virtual void foo() {} };
class Derived : public Base { int extra; };
Base* pb = new Base;
Derived* pd1 = static_cast(pb); // 編譯通過,執行危險
Derived* pd2 = dynamic_cast(pb); // 回傳 nullptr,安全
Base* pb2 = new Derived;
Derived* pd3 = dynamic_cast(pb2); // 成功,指向完整 Derived
若基類指標實際指向基類物件,強制轉為衍生類指標並存取衍生類專有成員(如 extra),會導致記憶體越界、未定義行為。dynamic_cast 能在執行期偵測此情況並回傳 nullptr,是唯一安全的向下轉型方式。
dynamic_cast 還支援「交叉轉型」(Cross Cast):在同一繼承體系的不同分支間轉型。static_cast 會編譯錯誤,而 dynamic_cast 回傳 nullptr 表示失敗。
type_info。dynamic_cast 是唯一具備執行期類型檢查的向下轉型工具。