C++ 提供四個具備明確語意的轉型運算子,語法統一為:cast_operator<TargetType>(expression)。以下透過實戰範例說明各運算子的典型應用場景。
static_cast<Type>(obj)
dynamic_cast<Type>(obj)
const_cast<Type>(obj)
reinterpret_cast<Type>(obj)
dynamic_cast — 多型層次安全導航適用:基類指標/參考 → 派生類指標/參考(向下/橫向轉型),需多型類別(有虛函數)。
class Shape { virtual ~Shape() = default; };
class Circle : public Shape { void draw() {} };
Shape* sp = new Circle;
Circle* cp = dynamic_cast<Circle*>(sp); // 成功,cp 可呼叫 draw()
if (cp) cp->draw();
Shape& rs = *sp;
try {
Circle& rc = dynamic_cast<Circle>(rs); // 參考版失敗拋 bad_cast
} catch (std::bad_cast&) { /* 處理 */ }
static_cast — 編譯期靜態轉型適用:算術型別、層次向上轉型、void* 還原、列舉轉整數、確定安全的向下轉型。
// 算術
int i = 42;
double d = static_cast<double>(i);
// 類別層次
class Base { virtual ~Base() = default; };
class Derived : public Base {};
Derived* pd = new Derived;
Base* pb = static_cast<Base*>(pd); // 向上:安全
// 確知 pb 指向 Derived 物件
Derived* pd2 = static_cast<Derived*>(pb); // 向下:程式設計師擔保
// void* 還原
void* vp = pd;
Derived* pd3 = static_cast<Derived*>(vp);
reinterpret_cast — 位元層級重新解釋適用:指標互轉、指標↔整數、函式指標轉換(平台相關)。不改變位元,極度危險,僅用於底層互操作。
// 指標互轉
double* pd = new double(3.14);
int* pi = reinterpret_cast<int*>(pd); // 同一位址,不同型別解讀
// 指標轉整數(如儲存到整數欄位、哈希)
uintptr_t addr = reinterpret_cast<uintptr_t>(pd);
// 函式指標轉換(需極度小心呼叫慣例)
void (*fp)() = reinterpret_cast<void(*)()>(some_address);
const_cast — 移除/添加 cv 資格唯一合法用途:與不支援 const 的舊式 API 互操作,且確知物件原本非 const。
class CCTest {
int number = 0;
public:
void printNumber() const {
std::cout << "Before: " << number;
// 僅為示範:移除 this 的 const(實際應避免)
const_cast<CCTest*>(this)->number--;
std::cout << " After: " << number;
}
};
警告:對原本定義為 const 的物件執行寫入 → 未定義行為(可能置於唯讀記憶體段)。
| 場景 | 推薦運算子 | 備註 |
|---|---|---|
| int → double、enum → int | static_cast | 顯式化隱式轉換 |
| 基類指標 → 派生類指標(不確定型別) | dynamic_cast | 需 RTTI、多型類別 |
| 基類指標 → 派生類指標(確定型別) | static_cast | 零開銷,程式設計師擔保 |
| 指標 → 整數 / 異類指標互轉 | reinterpret_cast | 位元級,平台相關 |
| 移除 const 傳給舊 API | const_cast | 極少數情況,謹慎使用 |
std::variant(C++17)替代 reinterpret_cast 型別懲罰。std::any(C++17)替代 void* + static_cast。