explicit 關鍵字專門修飾單參數建構函式(或 C++11 起多參數含預設值建構函式),阻斷編譯器執行隱式型別轉換,防止非預期物件建立與語意混淆。本文系統解析隱式轉換機制、explicit 阻斷效果、複製初始化 vs 直接初始化差異、多參數建構函式適用性、現代 C++ 設計原則。
class MyClass {
public:
MyClass(int num); // 單參數建構函式
};
MyClass obj = 10; // ✅ 編譯通過:隱式轉換
// 等同於:
MyClass temp(10);
MyClass obj = temp; // 複製初始化
觸發場景:複製初始化(=)、函式引數傳遞、返回值、{} 初始化列表(C++11)。
class MyClass {
public:
explicit MyClass(int num); // 顯式建構函式
};
MyClass obj = 10; // ❌ 編譯錯誤:無隱式轉換
MyClass obj(10); // ✅ 直接初始化:合法
MyClass obj{10}; // ✅ 列表初始化:合法
MyClass obj = MyClass(10); // ✅ 顯式建構:合法
| 形式 | 語法 | explicit 影響 |
|---|---|---|
| 複製初始化 | T obj = expr; | ❌ 禁止 |
| 直接初始化 | T obj(expr); | ✅ 允許 |
| 列表初始化 | T obj{expr}; | ✅ 允許 (C++11) |
| 函式引數 | func(T obj) | ❌ 禁止隱式轉換 |
| 返回值 | return expr; | ❌ 禁止隱式轉換 |
class A {
public:
explicit A(int x, int y = 0); // 含預設參數
};
A a = 10; // ❌ 編譯錯誤:單實參匹配,explicit 生效
A a(10); // ✅ 合法
只要單一實參即可匹配建構,explicit 即生效阻斷。
class B {
public:
explicit operator bool() const; // 顯式轉換函式
};
B b;
if (b) { ... } // ✅ 語境轉換允許
bool flag = b; // ❌ 複製初始化禁止
bool flag = static_cast<bool>(b); // ✅ 顯式轉換允許
unique_ptr、shared_ptr、string_view 皆為 explicitcomplex、ratio 等支援自然數學轉換explicit 是防禦性程式設計的利器:「預設顯式,按需隱式」。它將隱式轉換從「編譯器預設行為」轉為「開發者有意識選擇」,大幅減少非預期物件建立、語意混淆與難以追蹤的 Bug。現代 C++ 核心指南(C.46)明確建議:單參數建構函式預設加 explicit。