C++ Primer 第14章聚焦運算符重載與類型轉換,本文精選典型習題,從輸入輸出運算符、算術/關係運算符、賦值/下標/調用運算符到類型轉換運算符、lambda與函數對象,提供標準答案與核心解析,助你掌握類設計精髓。
| 運算符類別 | 建議形式 | 關鍵規則 |
|---|---|---|
輸入/輸出 << >> | 非成員友元 | 左操作數為流對象,不可為成員 |
算術 + - * / | 非成員 | 利用復合賦值 += 實現,保證對稱性 |
復合賦值 += -= | 成員 | 修改左操作數狀態,返回 *this |
關係 == < | 非成員 | 支持隱式轉換,符合直覺 |
賦值 = | 成員 | 處理自賦值,釋放舊資源,深拷貝 |
下標 [] | 成員 | 提供 const 非 const 兩版本 |
遞增/遞減 ++ -- | 成員 | 前綴返回引用,後綴返回舊值副本 |
解引用 * 箭頭 -> | 成員 | 智能指針/迭代器必備 |
函數調用 () | 成員 | 實現函數對象,可保存狀態 |
| 類型轉換 | 成員 | 單參數構造函數配合 explicit 控制隱式轉換 |
&& || 重載失去短路求值;優先級/結合性/操作數個數不變。= () [] -> 必須為成員;<< >> == + 建議非成員;修改狀態的(+= ++)為成員。// Date 類輸出運算符
ostream& operator<<(ostream& os, const Date& d) {
return os << "year:" << d.year << '\t' << "month:" << d.month << '\t' << "day:" << d.day << endl;
}
// Sales_data 輸出
ostream& operator<<(ostream& os, const Sales_data& item) {
return os << item.isbn() << ' ' << item.units_sold << ' ' << item.revenue;
}
輸入運算符必須檢查流狀態,失敗時將對象置為默認狀態:
istream& operator>>(istream& is, Date& dt) {
is >> dt.year >> dt.month >> dt.day;
if (!is) dt = Date(0,0,0); // 輸入失敗重置
return is;
}
標準模式:operator+ 調用 operator+=,避免代碼重複,性能無損(RVO優化):
Sales_data operator+(const Sales_data& lhs, const Sales_data& rhs) {
Sales_data sum = lhs; sum += rhs; return sum;
}
Sales_data& Sales_data::operator+=(const Sales_data& rhs) {
units_sold += rhs.units_sold; revenue += rhs.revenue; return *this;
}
反模式:+= 調用 + 會創建臨時對象,效率低、可讀性差。
Sales_data& operator=(const string& isbn):支持 ISBN 字符串直接賦值。StrVec& operator=(initializer_list<string>):支持列表初始化賦值。Date),默認拷貝/移動賦值足夠,無需自定義。// StrBlob 下標
string& operator[](size_t n) { return data[n]; }
const string& operator[](size_t n) const { return data[n]; }
// StrBlobPtr 遞增/遞減(前綴/後綴)
StrBlobPtr& operator++() { check(curr, "increment past end"); ++curr; return *this; }
StrBlobPtr operator++(int) { StrBlobPtr ret = *this; ++*this; return ret; }
// 指針算術
StrBlobPtr operator+(int n) { StrBlobPtr ret = *this; ret.curr += n; return ret; }
operator() 可接受任意數量參數(含0個)。bind2nd、not_equal_to、greater 等配合算法使用。
// 統計 >1024 的個數
count_if(vec.begin(), vec.end(), bind2nd(greater(), 1024));
// 找第一個不等於 "pooh" 的字符串
find_if(vec.begin(), vec.end(), bind2nd(not_equal_to(), "pooh"));
// 所有值乘2
transform(vec.begin(), vec.end(), vec.begin(), bind2nd(multiplies(), 2));
explicit operator bool() 防止意外隱式轉換,僅用於條件判斷。operator int()。const/非 const 重載。explicit,避免驚喜轉換。