當需要以類別 B 的物件隱式建構類別 A 物件,但受限於以下條件時:
A 的私有成員需由 B 提供,且 B 未宣告 A 為友元A 為第三方庫類別,無法修改其定義新增轉換建構函式標準做法(在 A 中加入 A(const B&))失效。此時可利用 C++ 的使用者定義型別轉換函式,在 B 中實現 operator A() 達成目標。
class A {
public:
explicit A(int n) : val(n) {}
void print() const { std::cout << val << '\n'; }
private:
int val;
};
class B {
public:
void setVal(int v) { data = v; }
// 關鍵:定義隱式轉換至 A
operator A() const { return A(data); }
private:
int data;
};
定義 operator A() 後,下列情境將自動調用:
A objA = objB;(複製初始化)
void func(A); func(objB);std::vector<A> vec; vec.push_back(objB);A factory() { B b; b.setVal(42); return b; }#include <iostream>
#include <vector>
class A {
public:
explicit A(int n) : a(n) {}
void print() const { std::cout << a << '\n'; }
private:
int a;
};
class B {
public:
operator A() const { return A(b); }
void setVal(int v) { b = v; }
private:
int b;
};
int main() {
B objB;
objB.setVal(5);
A objA(objB); // 隱式轉換建構
objA.print(); // 輸出 5
std::vector<A> vecA;
vecA.push_back(objB); // 隱式轉換入容器
vecA[0].print(); // 輸出 5
objB.setVal(10);
vecA.push_back(objB); // 再次轉換
vecA[1].print(); // 輸出 10
return 0;
}
C++11 引入 explicit operator A() const,阻止隱式轉換,僅允許顯式轉型:
explicit operator A() const { return A(b); }
// 使用時需:A a = static_cast<A>(b); 或 A a(b);
建議預設加上 explicit,除非業務邏輯確實需要隱式轉換語意,避免驚人的隱式行為導致難以除錯的錯誤。
若 A 管理動態資源(智慧指標、檔案控制代碼等),轉換操作符應執行深層複製或移動語意:
operator A() const { return A(*this); } // 複製
operator A() && { return A(std::move(*this)); } // 移動(C++11)
若同時在 A 定義 A(const B&) 且在 B 定義 operator A(),會造成雙向隱式轉換,編譯器在某些語境下會報「歧義」錯誤。原則:單向轉換,單一來源。
轉換操作符 operator Type() 是 C++ 類別設計的進階利器,能在無法修改目標類別時,從來源類別實現隱式建構語意。善用 explicit、移動語意與單向原則,可編寫出既符合直覺又型別安全的程式碼。此技巧常見於:
operator bool() 實現條件判斷const char* 兼容 C API