當調用一個重載函數和重載運算符時,編譯器通過把您所使用的參數類型和定義中的參數類型相比較,巨鼎選用最合適的定義。(重載決策)
重載運算符時帶有特殊名稱的函數,函數名是由關鍵字operator
和其后要重載的運算符符號構成,與其他函數一樣,重載運算符有一個返回類型和一個參數列表。
返回類型 operator 運算符(參數列表)
{...
}
大多數的重載運算符可被定義為不同的非成員函數,或者定義為類成員函數。
不可重載的運算符:
.
成員訪問運算符.*
->*
成員指針訪問運算符::
域運算符?:
條件運算符#
預處理符號
輸入輸出運算符重載
首先我們需要對流輸入輸出的原理有一個簡單的理解。
cin
是istream
類的對象,cout
是ostream
類的對象
cin>>x;
相當于cin.operator>>x;
然后會在輸入緩沖區中讀入整型數據后返回流輸入對象cin
,方便以后再次輸入。
我們可以傳統的寫法進行運算符重載:
例如:
#include <iostream>
using namespace std;class Distance
{
private:int feet; // 0 到無窮int inches; // 0 到 12
public:// 所需的構造函數Distance() {feet = 0;inches = 0;}Distance(int f, int i) {feet = f;inches = i;}ostream& operator<<(ostream& os){os << "英寸:" << feet << "\n英尺:" << inches;return os;}
};
int main()
{Distance d1(20, 18);d1 << cout << endl<< "成功"<< endl;//相當于d1.operator<<(cout)
}
運行結果:
這樣寫雖然可以但是不太符合我們的習慣,我們更習慣將cout
放到最左邊。為了能夠適用這種寫法,我們需要使用友元函數。
詳見代碼:
#include <iostream>
using namespace std;class Distance
{
private:int feet; // 0 到無窮int inches; // 0 到 12
public:// 所需的構造函數Distance() {feet = 0;inches = 0;}Distance(int f, int i) {feet = f;inches = i;}friend ostream& operator<<(ostream& os,const Distance& x){os << "英寸:" << x.feet << "\n英尺:" << x.inches;return os;}
};
int main()
{Distance d1(20, 18);cout<< d1 << endl<< "成功"<< endl;//相當于d1.operator<<(cout)
}
這樣寫起來就顯得很自然。這里我們通過友元函數進行重載。因為<<是二元操作符的緣故我們需要兩個參數。其他操作符也可以使用友元函數進行重載,只需要將操作對象放到參數列表中即可。
自增自減運算符的重載
因為自增自減運算符有前綴和后綴之分,因此在重載時也有所不同。除去實現上的不同,后綴運算符在重載的時候參數列表需要有一個int
,來向編譯器說明這是一個后綴形式 。例如:
返回類型 operator++ (int)
{}
自增和自減運算符一般是改變對象的狀態,所以一般是重載為成員函數。
在實際實現的時候,對于前綴運算符我們直接改變成員的狀態然后返回一個相同的成員。對于后綴運算符我們先創建一個對象保存對象的值,然后進行改變,最后返回原來的值。
例如:
#include <iostream>
using namespace std;class Time
{private:int hours; // 0 到 23int minutes; // 0 到 59public:// 所需的構造函數Time(){hours = 0;minutes = 0;}Time(int h, int m){hours = h;minutes = m;}// 顯示時間的方法void displayTime(){cout << "H: " << hours << " M:" << minutes <<endl;}// 重載前綴遞增運算符( ++ )Time operator++ () {++minutes; // 對象加 1if(minutes >= 60) {++hours;minutes -= 60;}return Time(hours, minutes);}// 重載后綴遞增運算符( ++ )Time operator++( int ) {// 保存原始值Time T(hours, minutes);// 對象加 1++minutes; if(minutes >= 60){++hours;minutes -= 60;}// 返回舊的原始值return T; }
};
int main()
{Time T1(11, 59), T2(10,40);++T1; // T1 加 1T1.displayTime(); // 顯示 T1++T1; // T1 再加 1T1.displayTime(); // 顯示 T1T2++; // T2 加 1T2.displayTime(); // 顯示 T2T2++; // T2 再加 1T2.displayTime(); // 顯示 T2return 0;
}
賦值運算符重載
詳見實例:
#include <iostream>
using namespace std;class Distance
{private:int feet; // 0 到無窮int inches; // 0 到 12public:// 所需的構造函數Distance(){feet = 0;inches = 0;}Distance(int f, int i){feet = f;inches = i;}void operator=(const Distance &D ){ feet = D.feet;inches = D.inches;}// 顯示距離的方法void displayDistance(){cout << "F: " << feet << " I:" << inches << endl;}};
int main()
{Distance D1(11, 10), D2(5, 11);cout << "First Distance : "; D1.displayDistance();cout << "Second Distance :"; D2.displayDistance();// 使用賦值運算符D1 = D2;cout << "First Distance :"; D1.displayDistance();return 0;
}
函數調用運算符()重載
重載函數的參數列表就是()
應該加上的內容
#include <iostream>
using namespace std;class Distance
{private:int feet; // 0 到無窮int inches; // 0 到 12public:// 所需的構造函數Distance(){feet = 0;inches = 0;}Distance(int f, int i){feet = f;inches = i;}// 重載函數調用運算符Distance operator()(int a, int b, int c){Distance D;// 進行隨機計算D.feet = a + c + 10;D.inches = b + c + 100 ;return D;}// 顯示距離的方法void displayDistance(){cout << "F: " << feet << " I:" << inches << endl;}};
int main()
{Distance D1(11, 10), D2;cout << "First Distance : "; D1.displayDistance();D2 = D1(10, 10, 10); // invoke operator()cout << "Second Distance :"; D2.displayDistance();return 0;
}
下標運算符[]重載
同樣的,重載函數的參數列表應該和[]
中的內容相同。
類成員訪問運算符->重載
成員訪問運算符可以被重載,只是比較麻煩。它被定義為為一個類賦予指針行為。
- ->必須是一個成員函數
- 返回類型必須是指針或者類的對象
類成員訪問運算符->
通常與指針引用運算符*
結合使用。用于實現“智能指針”的功能。這些指針可以自動執行一些操作,如在刪除指針的時候同時析構對象等來防止一些內存泄漏的問題。
想要了解更多可以參見:傳送門