兩種轉換方向
- 內置 → 用戶類型:依靠轉換構造函數(單參數構造函數)。
- 用戶類型 → 內置/其他類型:依靠類型轉換運算符(
operator Type())。
轉換構造函數
class MyInt {
int val;
public:
MyInt(int v = 0) : val(v) { cout << "Conv Ctor\n"; } // 隱式轉換
explicit MyInt(double d) : val((int)d) { cout << "Explicit Ctor\n"; } // C++11 explicit 阻止隱式
int get() const { return val; }
};
void foo(MyInt x) { cout << x.get() << endl; }
int main() {
foo(10); // 隱式調用 MyInt(10)
foo(3.14); // 編譯錯誤:explicit 禁止 double→MyInt 隱式轉換
foo(MyInt(3.14)); // 顯式構造 OK
}
類型轉換運算符
class Rational {
int num, den;
public:
Rational(int n, int d) : num(n), den(d) {}
operator double() const { return (double)num / den; } // 隱式轉換為 double
explicit operator bool() const { return num != 0; } // C++11 explicit bool
};
int main() {
Rational r(3, 2);
double d = r; // 隱式調用 operator double()
if (r) { ... } // 調用 operator bool(),用於條件判斷
// int i = r; // 錯誤:無 operator int()
}
雙向轉換綜合示例
class Number {
int val;
public:
Number(int v = 0) : val(v) { cout << "Ctor " << val << endl; }
Number(const Number& o) : val(o.val) { cout << "Copy " << val << endl; }
operator int() const { cout << "To int\n"; return val; }
Number& operator=(const Number& o) { cout << "Assign\n"; val = o.val; return *this; }
};
int main() {
Number a = 5; // Ctor 5
Number b = a + 3; // a.operator int() → 5+3=8 → Ctor 8
a = 10; // Ctor 10 → Assign → ~Ctor(臨時對象)
}
最佳實踐與避坑指南
- 單參數構造函數**默認加
explicit**,除非確確實實需要隱式轉換語義。
- 轉換運算符**盡量加
explicit**(C++11 支持),避免驚人的隱式轉換鏈。
- 提供命名轉換函數(
to_int()、to_string())作為顯式替代方案。
- 避免雙向隱式轉換導致的歧義:
Number n = 1; int x = n; 看似自然,但複雜表達式極易出錯。