運算子多載讓**使用者定義型別(類別)**能像內建型別一樣使用標準運算子,提供**直覺介面**,降低學習曲線、減少錯誤。本質是**函數呼叫的語法糖**。
// 無多載:難以閱讀
Fred f = add(add(mul(a,b), mul(b,c)), mul(c,a));
// 有多載:自然數學表達
Fred f = a*b + b*c + c*a;
| 運算式 | 語意 |
|---|---|
myString + yourString | 字串串接 |
myDate++ | 日期加一天 |
a * b | 數值/矩陣相乘 |
a[i] | 陣列/容器存取 |
x = *p | 智慧指標解參考(可觸發磁碟 I/O) |
class Array {
public:
int& operator[](unsigned i); // 開發者覺得語法怪異
private:
int data[100];
};
// 但使用者程式碼極其清晰
int main() {
Array a;
a[3] = 4; // 直覺易懂
}
**核心觀念**:重用世界中,使用者眾多、開發者寡少,API 設計應優先照顧使用者體驗。
.、?:、sizeof、::、.*new/delete、()、[]、->、++/-- 等)**(冪次),優先級/結合性/元數皆由語言固定
class Matrix {
public:
Matrix(unsigned rows, unsigned cols);
double& operator()(unsigned row, unsigned col);
double operator()(unsigned row, unsigned col) const;
// 複製/移動/解構...
private:
unsigned rows_, cols_;
double* data_; // 扁平化儲存
};
inline double& Matrix::operator()(unsigned r, unsigned c) {
if (r >= rows_ || c >= cols_) throw BadIndex("out of bounds");
return data_[cols_ * r + c];
}
// 使用語法:m(5,8) = 106.15;
operator[] 只能單參數,operator() 可接受任意參數數量[][] 鎖定雙重陣列結構operator() 更優**介面優先,實作次之**。以 Stack 為例:
// 錯誤:洩漏實作細節
class Stack {
public:
LinkedList& getList(); // 使用者不關心 LinkedList
private:
LinkedList list_;
};
// 正確:提供領域語彙操作
class Stack {
public:
void push(int x);
int pop();
bool empty() const;
private:
LinkedList list_; // 完全封裝
};
LinkedList 不應暴露 Node 指標,應提供 LinkedListIterator:
class LinkedListIterator {
public:
bool operator==(const LinkedListIterator&);
bool operator!=(const LinkedListIterator&);
void operator++(); // 前進
int& operator*(); // 解參考取值
private:
Node* p_;
friend class LinkedList;
};
class LinkedList {
public:
LinkedListIterator begin();
LinkedListIterator end(); // 回傳 NULL 迭代器
void append(int);
void prepend(int);
private:
Node* first_;
};
// 使用者程式碼:標準 STL 風格
void userCode(LinkedList& a) {
for (auto p = a.begin(); p != a.end(); ++p)
std::cout << *p << '\n';
}
get/set)std::vector、std::list、std::map 等 STL 容器+ 應回傳新物件,+= 修改現有物件operator[]、operator() 皆需 const 多載