首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++ dynamic_cast 深度解析:原理、用法與安全性對比

     編輯:關於C++

四種類型轉換運算子

運算子用途執行期檢查
static_cast編譯期已知的相關類型轉換 (如基礎型別、類別層級向上/向下)無
dynamic_cast多態類別層級的**安全向下轉型****有** (需 RTTI)
const_cast移除/添加 const/volatile無
reinterpret_cast底層位元模式重新解讀 (極度危險)無

dynamic_cast 核心前提

  • **基類必須擁有至少一個虛函數** (通常是虛解構子),確保類別具有多態性與虛函數表 (vtable)。
  • 僅適用於**指標**或**參考**類型。
  • 向下轉型失敗時:指標回傳 nullptr,參考拋出 std::bad_cast 例外。

實戰範例:安全 vs 危險

class Base { public: virtual ~Base() {} int m_iNum; };
class Derived : public Base { public: char* m_szName; };

int main() {
    Base* pb = new Derived("abc"); // 基類指標指向衍生物件

    // 1. 正確向下轉型:衍生 -> 基類指標實際指向衍生物件
    Derived* pd1 = static_cast(pb); // 編譯期信任,無檢查
    Derived* pd2 = dynamic_cast(pb); // 執行期檢查,安全
    // 兩者皆可正常存取 pd->m_szName

    // 2. 危險向下轉型:基類指標指向基類物件
    Base* pb2 = new Base();
    Derived* pd3 = static_cast(pb2); // 編譯通過,執行期未定義行為 (存取 m_szName 會崩潰)
    Derived* pd4 = dynamic_cast(pb2); // 回傳 nullptr,安全失敗

    cout << pd3 << endl; // 非零位址 (假象)
    cout << pd4 << endl; // 0 (nullptr)
}

記憶體佈局驗證 (64 位系統)

cout << sizeof(Base) << endl;      // 16 (vptr 8 + int 4 + padding 4)
cout << sizeof(Derived) << endl;   // 24 (Base 16 + char* 8)
cout << sizeof(*pb) << endl;       // 16 (靜態類型 Base*,只知 Base 大小)

注意:sizeof(*pb) 看的是靜態類型 Base 的大小,而非動態類型 Derived。

效能考量

dynamic_cast 需走 RTTI 機制,遍歷繼承圖檢查類型關係,比 static_cast 慢。在效能敏感熱路徑,若能確保型別正確,優先用 static_cast;否則寧可犧牲效能換取安全。

最佳實踐

  1. 基類**一定要宣告虛解構子** (或任一虛函數)。
  2. 盡量減少向下轉型需求,透過虛函數多態設計替代。
  3. 必須向下轉型時,首選 dynamic_cast 並檢查回傳值。
  4. 關閉 RTTI (如 -fno-rtti) 會導致 dynamic_cast 編譯失效。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved