在 C++ 中,operator 關鍵字主要有兩個用途:一是運算符重載,二是自定義類型的隱式轉換。運算符重載對大多數開發者並不陌生,但隱式類型轉換的用法往往被忽視。本文將透過一個完整的範例,回顧這兩種用法,並展示如何利用隱式轉換實現一個通用的 string_cast 工具,將 std::string 优雅地轉換為各種基本數據類型。
#include <iostream>
#include <sstream>
using namespace std;
class FuncObj {
public:
FuncObj(int n) : _n(n) {
cout << "constructor" << endl;
}
// 1. 運算符重載:重載 () 使對象成為函數對象
bool operator()(int v) {
cout << "operator overload" << endl;
return v > _n;
}
// 2. 隱式類型轉換:定義轉換至 string 的運算符
operator string() {
cout << "type convert" << endl;
stringstream sstr;
sstr << _n;
return sstr.str();
}
private:
int _n;
};
int main() {
FuncObj obj(10);
// 使用運算符重載:obj 像函數一樣被調用
if (obj(11))
cout << "11 greater than 10" << endl;
// 使用隱式轉換:FuncObj 自動轉為 string
string str(obj);
cout << str << endl;
}
bool operator()(int v) 是運算符重載,使 FuncObj 成為函數對象,可用於 STL 算法中。operator string() 定義了從 FuncObj 到 string 的隱式轉換。注意:轉換運算符的聲明中,operator 關鍵字出現在返回類型之前,且不寫返回類型,這與運算符重載語法不同。string str(obj); 利用了構造函數的隱式轉換特性。雖然 string 沒有接受 FuncObj 的構造函數,但因為 FuncObj 可隱式轉為 string,編譯器會先生成一個臨時 string 再調用拷貝構造函數。constructor
operator overload
11 greater than 10
type convert
10
構造函數的隱式轉換是「用其他類型構造當前類的臨時對象」,方向是 外部 → 內部;而 operator 隱式轉換是「用當前對象生成另一種類型的對象」,方向是 內部 → 外部。前者可用 explicit 關鍵字禁止,後者則可改用顯式轉換函數(如 to_string())替代,以增強代碼可控性。
利用隱式轉換運算符,我們可以實現一個語法類似 static_cast 的字串轉換工具:
template <typename T>
class string_cast {
public:
string_cast(const std::string &from) : m_from(from) {}
// 隱式轉換運算符:將 string 轉為目標類型 T
operator T() const {
std::stringstream sstr(m_from);
T ret;
try {
sstr >> ret;
} catch (std::exception &e) {
return T(0); // 轉換失敗返回 0
}
return ret;
}
private:
const std::string &m_from;
};
cout << string_cast<int>("12345") << endl; // 輸出 12345
cout << string_cast<double>("12345.78") << endl; // 輸出 12345.78
這種寫法與 C++ 風格的轉換運算符(static_cast、dynamic_cast 等)語法一致,既簡潔又具備類型安全。注意:此實現僅適用於支援 operator>> 的類型,且錯誤處理較為簡單,生產環境中可根據需要擴展。