## 一.總則
1. 對于類類型,重載運算符一般使用 **引用** 作為參數,來避免不必要的復制。
2. 為了增加對 **常對象** 的支持,建議將 類類型參數 設置為 **常引用** ,對于在類內重載的運算符,可以將該函數設置為 **常成員函數** 。
3. 返回值不一定是 **引用** ,更不能是局部變量的引用(除了 **引用參數** )。
## 二.重載算術運算符(位運算符類似)
1. 算術運算符的操作細節:將計算結果放入新的對象,并返回。 **注意不要返回引用。**
2. 一般將雙目算術運算符重載為友元或普通函數,將單目算術運算符重載為成員函數。
3. 一般情況下,算術運算符中 `+` 和 `*` 需要滿足不同類型之間的交換律。為了滿足這個需求,一般需要:
+ 重載為友元或普通函數。因為將這些運算符重載為普通函數,要求第一個操作數必須是該類的對象。
+ 添加 **轉換構造函數** ,使得其他類型的數據可以轉換到該類。
```c++
//重載示例
T1 operator+(const T1&,const T2&);
T1 operator+(const T2&,const T1&);
//如果你的類有轉換構造函數,可以把T2 轉換成 T1,也可以這么寫:
T1 operator+(const T1&,const T1&);
```
4. 注意除法和取余中,第二個操作數為 `0` 的情況。
## 二.重載賦值運算符
1. 為滿足 **鏈式調用** 的需求,應該設置返回值為第一個操作對象的引用。
2. 只能將該運算符重載為成員函數。
3. 一般不需要定義常成員函數版本。你會對一個常量賦值嘛?
```c++
//鏈式調用
a=b=c=d=e;
//拷貝賦值運算符重載示例
T& T::operator=(const T&);
//[11+][$]移動賦值運算符重載示例
T& T::operator=(const T&&);
```
## 三.重載復合賦值運算符
1. 復合賦值運算符的操作細節:將計算結果放入第一個運算對象,并返回 **其引用** 。
2. 一般將復合賦值運算符重載為成員函數。
3. 注意除法和取余中,第二個操作數為 `0` 的情況。
4. 一般不需要定義常成員函數版本。你會對一個常量賦值嘛?
```c++
//鏈式調用
a+=b;
//重載示例
T& T::operator+=(const T2&);
```
## 四.重載關系運算符
1. 因為這些運算符功能幾乎差不多,因此可以先寫一個專用函數用于比大小。
例如,大于返回1,等于返回0,小于返回 -1。
然后這些重載函數的內容基本上就是一句話的事。
2. 返回值應該為 `bool` 。
```c++
int T::compare(const T&) const;
bool operator>(const T& t1,const T& t2)
{
return t1.compare(t2) > 0;
}
bool operator<(const T& t1,const T& t2)
{
return t1.compare(t2) < 0;
}
bool operator==(const T& t1,const T& t2)
{
return t1.compare(t2) == 0;
}
```
## 五.重載前置遞增遞減運算符
1. 一般類內重載前置遞增遞減運算符,不需要偽參數。
2. **需要返回遞增后自身的引用** 。
3. 一般不需要定義常成員函數版本。你會對一個常量遞增遞減嘛?
```c++
//重載
T& T::operator++();
T& T::operator--();
//調用
T i;
++i;
--i;
```
## 六.重載后置遞增遞減運算符
1. 一般類內重載后置遞增遞減運算符。
2. 為了區分前置遞增遞減運算符,需要加上一個 **偽參數** 。
3. **需要返回遞增遞減前的自身** 。
4. 一般不需要定義常成員函數版本。你會對一個常量遞增遞減嘛?
```c++
//返回遞增遞減前的自身對象
T T::operator++(int);
T T::operator--(int);
//調用
T i;
i++;
i--;
```
## 七.重載數組下標運算符
1. 只能重載為成員函數。
2. 可以通過賦值語句來修改運算結果并影響到對象自身,因此需要返回 **引用** 。
3. 注意檢查下標范圍。
```c++
T& T::operator[](int);
const T& T::operator[](int) const;
```
## 八.重載解引用運算符
1. 運算結果為一個 **左值** ,因此需要返回引用。
```c++
T& T::operator*();
const T& T::operator*() const;
```
## 九.重載指針的成員運算符
1. 該運算符非常特殊,雖然它是雙目運算符,但它的重載函數 **沒有參數**。
2. 返回值為一個可以進行 **指針的成員訪問** 的指針。
3. 必須在類內重載。
```c++
//注: T1* 可以進行 `->` 操作
T1* T::operator->();
const T1* T::operator->() const;
//相當于: t1.operator->()->t2;
t1->t2;
```
## 十.重載函數調用運算符
1. 效果:可以像函數一樣使用對象。
2. 只能在類內重載。
```c++
int T::operator()(int i,double d);
```
## 十一.重載插入和提取運算符
只能在類外重載。
```c++
ostream& operator<<(ostream& os,const T& obj);
istream& operator>>(istream& is,T& obj);
```
## 十二.罕見的運算符重載
1. `&(取地址)` 沒有必要重載,因為它可以作用于任何類型的左值,表示取地址。
2. `,(逗號)` 可能會改變運算符本身的求值順序。重載有負作用。
3. **邏輯運算符** 會失去其短路求值的特性。考慮到其負作用,一般使用類類型到 `bool` 的類型轉換來代替邏輯運算符的重載。
4. `->*(指針的成員指針)` 。沒有什么問題,但很少有類使用它。
- 閱讀說明
- 1.1 概述
- C++基礎
- 1.2 變量與常量
- 1.2.1 變量
- 1.2.2 字面值常量
- 字符型常量
- 數值型常量
- 1.2.3 cv限定符
- 1.3 作用域
- 1.3.1 標識符
- 1.3.2 *命名空間
- 1.3.3 作用域
- 1.3.4 可見性
- 1.4 數據類型
- 1.4.1 概述
- 1.4.2 處理類型
- 類型別名
- * auto說明符
- * decltype說明符
- 1.4.3 數組
- 1.4.4 指針
- 1.4.5 引用
- 1.5 表達式
- 1.5.1 概述
- 1.5.2 值的類別
- 1.5.3 *初始化
- 1.5.4 運算符
- 算術運算符
- 邏輯和關系運算符
- 賦值運算符
- 遞增遞減運算符
- 成員訪問運算符
- 位運算符
- 其他運算符
- 1.5.5 *常量表達式
- 1.5.6 類型轉換
- 第2章 面向過程編程
- 2.1 流程語句
- 2.1.1 條件語句
- 2.1.2 循環語句
- 2.1.3 跳轉語句
- 2.1.4 *異常處理
- 2.2 函數
- 2.2.1 概述
- 2.2.2 函數參數
- 2.2.3 內置函數
- 2.2.4 函數重載
- 2.2.5 * 匿名函數
- 2.3 存儲和生命期
- 2.3.1 生命周期與存儲區域
- 2.3.2 動態內存
- 2.4 *預處理命令
- 第3章 面向對象編程
- 3.1 概述
- 3.2 類和對象
- 3.3 成員
- 3.3.1 訪問限制
- 3.3.2 常成員
- 3.3.3 靜態成員
- 3.3.4 成員指針
- 3.3.5 this指針
- 3.4 特殊的成員函數
- 3.4.1 概述
- 3.4.2 構造函數
- 3.4.3 析構函數
- 3.4.4 拷貝語義
- 3.4.5 * 移動語義
- 3.5 友元
- 3.6 運算符重載與類型轉換
- 3.6.1 概述
- 3.6.2 重載方法
- 3.6.3 類型轉換
- 3.7 繼承與多態性
- 3.7.1 概述
- 3.7.2 派生類
- 3.7.3 子類型
- 3.7.4 虛基類
- 3.7.5 虛函數
- 3.7.6 抽象類
- 3.8 模板與泛型
- 3.8.1 概述
- 3.8.2 模板類型
- 3.8.3 *模板參數
- 3.8.4 *模板編譯
- 3.8.5 *模板推斷
- 3.8.6 *實例化與特例化
- 第4章 C++標準庫
- 4.1 概述
- 4.2 輸入輸出流
- 4.2.1 概述
- 4.2.2 *流的狀態
- 4.2.3 *常用流
- 4.2.4 *格式化I/O
- 4.2.5 *低級I/O
- 4.2.6 *隨機訪問
- 4.3 *C輸入輸出
- 4.3.1 *字符輸入輸出
- 4.3.2 *格式化輸入輸出
- 4.4 * 容器
- 4.4.1 * 概述
- 4.4.2 * 基本操作
- 4.4.3 * 順序容器
- 4.4.4 * 迭代器
- 4.4.5 * 容器適配器
- 4.5 * 泛型算法
- 4.6 * 內存管理
- 4.6.1 * 自動指針
- 4.7 * 其他設施