原文:http://www.cnblogs.com/alex-tech/archive/2011/03/27/1997045.html
重載運算符是對正常函數的語法美化.沒給語言增加任何基本的東西,但改善了可理解性並降低維護費用.當用戶需要時,就應該使用運算符重載,但應該僅僅以用戶熟悉的語義方式來使用它。
1. 重載規則
不能重載的運算符: . 和 .* 和 ?: 和 :: 和 sizeof 和 typeid
重載運算符有兩種基本選擇: 類的成員函數或者友元函數, 建議規則如下:
所有一元運算符: 成員函數
= () [] ->: 必須是成員函數
+= -= /= *= ^= &= != %= >>= <<=: 成員函數
所有其它二元運算符, 例如: –,+,*,/ : 友元函數
2. 參數和返回值
當參數不會被改變,一般按const引用來傳遞(若是使用成員函數重載,函數也爲const).
對於返回數值的決定:
1) 如果返回值可能出現在=號左邊, 則只能作爲左值, 返回非const引用。
2) 如果返回值只能出現在=號右邊, 則只需作爲右值, 返回const型引用或者const型值。
3) 如果返回值既可能出現在=號左邊或者右邊, 則其返回值須作爲左值, 返回非const引用。
3. 幾個例子
3.1 二元運算法建議使用友元函數重載,與內部類型的操作相似
3.1 二元運算法建議使用友元函數重載,與內部類型的操作相似
1: class Integer {
2: int _val;
3: public:
4: Integer(int val = 0) : _val(val) {}
5:
6: // 二元運算符重載爲成員函數
7: const Integer operator+(const Integer& i) const {
8: return Integer(_val + i._val);
9: }
10: // 二元運算符重載爲友元函數
11: friend const Integer operator-(const Integer& ,const Integer&);
12: };
13: const Integer operator-(const Integer& l,const Integer& r) {
14: return Integer(l._val-r._val);
15: }
16:
17: Integer a(40), b(12);
18:
19: a+b;
20: a+1; // 正確, 左操作數爲Integer對象, +按照Integer的成員函數解析右操作數爲1, 進行自動類型轉換
21: 1+a; // 錯誤, 左操作數爲1, +按照常規操作符解析, 而右操作符爲Integer對象,1無法進行轉化
22: a-b; // 正確
23: a-1; // 正確
24: 1-a; // 正確, 左操作數爲1, 而右操作符爲Integer對象,-作爲Integer的一個友元函數,1被轉化爲Integer對象
1) 在上面的代碼中, 二元操作符+作爲成員函數重載,在進行形如1+a之類的調用無法正確解析。二元操作符-作爲友元函數重載,使用方法與常規的-號操作符的操作類似。
2) 如上的運算符重載, 運算符的運算結果必定位於=號的右邊, 返回的是一個右值, 返回const型值。
3.2 ++與--運算符重載
1) operator++有兩種形式, 後綴形式i++, 它重載時有一類型爲int的虛參。前綴形式++i,它重載時沒有虛參.operator--情況類似。
2) 後綴形式(i++,i--)返回原狀態的拷貝(或者返回void), 前綴形式(++i, --i)通過引用返回*this。這是爲了和內部類型保持一致.
前綴版本(++i,--i)返回的是一個左值, 也就是返回一個非const引用.
後綴版本(i++,i--)返回的是一個右值, 也就是返回一個const型值
1: class Example{
2: public:
3: Example(int i,int j) { _x = i; _y = j;}
4: // 前綴形式(++i)重載的時候沒有虛參,通過引用返回*this,也就是返回變化之後的數值
5: const Example& Example::operator++ () {
6: ++_x;
7: ++_y;
8: return *this;
9: }
10: // 後綴形式(i++)重載的時候有一個int類型的虛參, 返回原狀態的拷貝
11: const Example Example::operator++ (int) {
12: Example tmp(*this);
13: ++_x;
14: ++_y;
15: return tmp;
16: }
17: int _x, _y;
18: };
19:
3.3 重載下標運算符[]
因爲下標運算符可以出現在=的左邊或右邊,因此它的返回值必須是個左值,一般是把返回值指定爲一個引用。而爲了能訪問const對象,下標運算符重載有非const和const兩個版本。
1: class Array {
2: public:
3: Array(int size) : _size(size) { _val = new int[_size];}
4: int& operator[] (int index) { return _val[index]; }
5: const int& operator[] (int index) const { return _val[index]; }
6: private:
7: int _size;
8: int* _val;
9: };
10: Array array_a(10);
11: array_a[0] = 1; // []的重載版本有非const版本
3.4 重載輸入輸出操作符
由於>>與<<操作符總是要被賦值,必須返回一個左值。
1: class A
2: {
3: private:
4: int a,b;
5: public:
6: A(int na = 0, int nb = 0):a(na), b(nb){}
7: friend istream& operator>>(istream& is, A& aa);
8: friend ostream& operator<<(ostream& os, const A& aa);
9:
10: };
11: ostream& operator<<(ostream& os, const A& aa) {
12: os << aa.a << " " << aa.b;
13: return os;
14: }
15:
16: istream& operator>>(istream& is, A& aa) {
17: is >> aa.a >> aa.b;
18: return is;
19: }
附送參考文獻一篇:http://bbs.bccn.net/thread-111936-1-1.html