單參數構造函數(或除第一參數外均有默認值)會定義隱式轉換:
class B {
public:
B(int x); // 可隱式 int -> B
void doSomething(B b);
};
B obj;
obj.doSomething(20); // 20 隱式轉換為 B(20) 再傳入
這可能導致意外行為(如非預期的臨時對象創建、性能損耗、語義錯誤)。
在構造函數聲明前加 explicit 禁止隱式轉換:
class B {
public:
explicit B(int x); // 禁止 int -> B 隱式轉換
void doSomething(B b);
};
obj.doSomething(20); // 編譯錯誤:無隱式轉換
obj.doSomething(B(20)); // 必須顯式構造
explicit 只能用於類內部構造函數聲明,不能用於類外定義。class Widget {
public:
explicit Widget(int id); // 禁止 int -> Widget
explicit Widget(const string& name); // 禁止 string -> Widget
Widget(const Widget&) = default; // 拷貝構造通常不加 explicit
Widget& operator=(const Widget&) = default;
};
void process(Widget w);
int main() {
process(10); // 錯誤:隱式轉換被禁止
process(Widget(10)); // 正確:顯式構造
process("name"); // 錯誤
process(Widget("name")); // 正確
}
explicit 是防止構造函數成為隱式轉換運算子的關鍵機制。掌握 explicit 是編寫健壯 C++ 類的基本功,體現「顯式優於隱式」的現代 C++ 設計哲學。