聊聊C++ 運算符重載知識
前言
1.運算符重載是一種形式的C++多態。
2.重載運算符可以使代碼看起來更加自然。
回顧類
在正常構造類的時候,有些成員方法可以不用寫出來,例如在這樣一個表示時間的類中,拷貝構造函數隻是淺拷貝,和系統默認的步驟是一樣的,可以不用寫瞭。 同樣,析構函數如果在對象死亡之前沒有必須要做的事情,也可以不用寫。
所以在下面的例子中,拷貝構造和析構函數可以省略。
class Time { public: Time(); Time(const Time& src) { _hour = src._hour; _minutes = src._minutes; } ~Time(); private: int _hour; int _minutes; };
通過示例引入運算符重載
示例
若要將兩個等數組中各個下標對應的字符相加,普通寫法為:
#include<iostream> using namespace std; int main(void) { const int SIZE = 10; int ch1[SIZE] = { 0,1,2,3,4,5,6,7,8,9 }; int ch2[SIZE] = { 9,8,7,6,5,4,3,2,1,0 }; int ch3[SIZE]; for (int i = 0; i < SIZE; ++i) { ch3[i] = ch1[i] + ch2[i]; } for (int i = 0; i < SIZE; ++i) { cout << ch3[i] << " "; } cout << endl; return 0; }
這樣是可以正常輸出的:
再來看看運算符重載的示例,這裡使用的是 string 類。
#include<iostream> #include<string> using namespace std; int main(void) { string s1 = "aaaa"; string s2 = "bbbb"; string s3 = s1 + s2; cout << s3 << endl; return 0; }
這裡的 s1 + s2就是運用的加法運算符重載,內部實現也是對應的下標再加,但這樣簡單的寫法,強調瞭實質。
定義
要重載運算符,需要使用被稱為運算符函數的特殊函數形式。
格式:
ret_form operator op(argument-list)
例如加法運算符:
operator +();
可重載的運算符
這裡開個玩笑,列出這寫可重載的,大傢有興趣可以自己實現。
本文講述的類
下面是文章示例的一個類:
表示一個復數
class Complex { public: //默認構造 Complex(); //構造函數 Complex(int a, int b) { _a = a; _b = b; } //打印 void show() { cout << _a << "+" << _b << endl; } //析構函數 ~Complex() { cout << "Program Exit" << endl; } private: int _a; //實部 int _b; //虛部 }
加法運算符
如果要使用到加法,如
int main(void) { Complex s1(1, 2); Complex s2(2, 3); Complex s3 = s1 + s2; return 0; }
那首先要確定,我不能改變加數原本的值,其次,我需要返回一個加完之後的類。
那重載加法運算符聲明就可寫成:
1.返回類型為 類 類型
2.this指針聲明成const
3.第二個加數聲明為const
Complex operator +(const Complex& src)const;
函數實現:
這裡還用到瞭構造函數,將其構造後返回。
//加法運算符 Complex operator +(const Complex& src)const { int a = _a + src._a; int b = _b + src._b; return Complex(a, b); }
使用運算符的兩種方式:
s3和s4用到的方式都可以
Complex s1(1, 2); Complex s2(2, 3); Complex s3 = s1 + s2; Complex s4 = s1.operator+(s2);
運行示例:
輸出瞭 s3 和s4, 並且析構。
&& 運算符
比如要寫一個方法來判斷兩個復數的實部是否都為0.
if (s1 && s2) { cout << "all zero" << endl; }
實現:
//&& bool operator &&(const Complex& src)const { return _a && src._a; }
cout<<運算符
想要重載輸出運算符,首先想到的是將 cout 當作參數傳遞給函數。
簡易版(相當於show())
//cout << void operator <<(ostream& out) { out << _a << "+" << _b << "i" << endl; }
這樣重載的話,就隻能當作show()方法一樣調用。而不能直接使用cout。
臻享版
首先要知道,cout是一個二元運算符,那我們傳遞參數的時候,也是傳遞兩個參數,向上面的簡易版,第一個參數為this指針, 第二個才是cout ,如果想把this指針移到第二個參數位置,是辦不到的,所以隻能當作show方法的樣子來寫。
void operator <<(/*this*/ostream& out) { out << _a << "+" << _b << "i" << endl; }
解決方法:
把要輸出的參數放在第二個位置。
這裡就需要在類外實現,實現的方法利用友元性質,放入類中。
如圖所示,我確實是在類外寫的。
運行示例:
這裡直接寫cout << s1
int main(void) { Complex s1(1, 2); Complex s2(2, 3); Complex s3 = s1 + s2; Complex s4 = s1.operator+(s2); s3.show(); s4.show(); //s1.operator<<(cout); cout << s1; return 0; }
沒有問題,把 1+2i 輸出瞭
但如果想要連續輸出,例如:
cout << s1 << s2;
我像上面那樣寫就不行瞭,因為這個方法的返回類型是void,函數參數先接收 cout 和 s1, 然後返回void,將void 和 s2又當作參數傳遞過去,顯然是不行的。
解決方法:
將這個方法的返回類型寫成輸出流對象, 即ostream
ostream& operator <<(ostream& out, const Complex& src) { out << src._a << "+" << src._b << "i" << endl; return out; }
同樣友元函數也寫成:
friend ostream& operator <<(ostream& out, const Complex& src);
這樣寫的話就可以連續輸出
示例:若要輸出三個對象
cout << s1 << s2 << s3;
運行結果
++運算符 前置++
前置++的意思是先 自加1,再返回。
實現:
這裡隻針對復數的實部
//前置++ Complex& operator ++() { ++_a; return *this; }
後置++
後置++的意思是先傳值,再自增1 。
實現:
參數列表裡的int沒有實質意義,隻是讓編譯器區分前置還是後置。
//後置++ Complex operator ++(int) { int tmp = _a; _a++; return Complex(tmp, _b); }
練習
通過上面介紹的這些運算符重載,可以寫出其他一些。
這裡可以實現有
減法運算符、 ||運算符、 >>運算符 和 自減運算符(- -)。
例如減法運算符:和加法一樣的寫法:
//減法運算符 Complex operator -(const Complex& src)const { int a = _a - src._a; int b = _b - src._b; return Complex(a, b); }
到此這篇關於C++ 運算符重載 簡介的文章就介紹到這瞭,更多相關C++ 運算符重載內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- C++ 命名空間 using聲明使用示例詳解
- 詳解C++ const修飾符
- 詳解如何利用C++實現Mystring類
- C++輸入流和輸出流 超級詳細
- C++:函數對象,STL提供的函數對象,函數適配器詳解