文章目錄
- 前言
- 一、 類型檢查的時機
- 二、安全性
- 三、適用場景
- 四、代碼示例對比
- 總結
前言
在 C++ 中,dynamic_cast 和 static_cast 是兩種不同的類型轉換操作符,主要區別體現在類型檢查的時機、安全性和適用場景上。以下是它們的核心區別:
一、 類型檢查的時機
-
dynamic_cast:
運行時檢查。它會驗證轉換的合法性(比如指針或引用是否指向目標類型的有效對象)。如果轉換非法,對指針返回 nullptr,對引用拋出 std::bad_cast 異常。
要求類必須有虛函數(即多態類型),否則無法使用。 -
static_cast:
編譯時檢查。它信任開發者對類型安全的保證,不執行運行時檢查。如果轉換非法(比如無關類之間的轉換),可能導致未定義行為(UB)。
適用于編譯時已知類型關系的場景。
二、安全性
-
dynamic_cast:
更安全,但需要運行時開銷(RTTI)。
主要用于多態類型的向下轉型(downcast)或交叉轉型(crosscast)。 -
static_cast:
不安全,但性能更高(無運行時開銷)。
需要開發者自行確保類型兼容性,否則可能導致錯誤。
三、適用場景
dynamic_cast 的典型用途
- 多態類型(有虛函數的類)的向下轉型:
class Base { virtual void foo() {} };
class Derived : public Base {};Base* ptr = new Derived;
Derived* derived_ptr = dynamic_cast<Derived*>(ptr); // 安全向下轉型
- 處理繼承層次中的交叉轉換(如多重繼承中的兄弟類轉換)。
static_cast 的典型用途
- 基本類型的顯式轉換(如 double → int):
double d = 3.14;
int i = static_cast<int>(d);
- 非多態類型的指針/引用轉換(需確保類型兼容):
Derived* d = new Derived;
Base* b = static_cast<Base*>(d); // 向上轉型(安全,無需 dynamic_cast)
- 顯式反向轉換(如 void* → int*):
void* vptr = some_address;
int* iptr = static_cast<int*>(vptr);
四、代碼示例對比
向下轉型(多態類型)
class Base { virtual void foo() {} }; // 必須有多態性(虛函數)
class Derived : public Base {};Base* base_ptr = new Derived;// 使用 dynamic_cast(安全,但需要虛函數)
Derived* derived_ptr1 = dynamic_cast<Derived*>(base_ptr); // 成功// 使用 static_cast(不安全,但強制轉換)
Derived* derived_ptr2 = static_cast<Derived*>(base_ptr); // 可能未定義行為(若實際類型不匹配)
class Base { virtual void foo() {} };
class Derived : public Base {};Base* ptr = new Derived;
Derived* derived_ptr = dynamic_cast<Derived*>(ptr); // 安全向下轉型
非多態類型轉換
class A {};
class B : public A {};A* a_ptr = new B;
B* b_ptr = static_cast<B*>(a_ptr); // 編譯通過,但無運行時檢查
// B* b_ptr = dynamic_cast<B*>(a_ptr); // 錯誤:A 不是多態類型(無虛函數)
總結
特性 | dynamic_cast | static_cast |
---|---|---|
類型檢查時機 | 運行時 | 編譯時 |
安全性 | 高(失敗返回 nullptr 或拋異常) | 低(依賴開發者保證) |
性能 | 有運行時開銷(RTTI) | 無開銷 |
適用類型 | 多態類型(需虛函數) | 任意類型(包括非多態) |
典型用途 | 向下轉型、交叉轉型 | 基本類型轉換、顯式向上/向下轉型 |
優先選擇 static_cast,除非需要處理多態類型的不確定轉換(此時用 dynamic_cast)。