“什麼是運算子的重載”與“為什麼要引入運算子多載?”這兩個問題,在這裡都不多說了,百度一下就都OK了
下面說了一下一些比較容易錯的重載,
首先看看模板們是如何聲明重載的
下是iterator 模板中的一段源碼,大家看看它的格式:
iterator 的一段源碼
typedef _Vector_iterator<_Ty, _Alloc> _Myt;reference operator*() const{// return designated objectreturn ((reference)**(_Mybase *)this);}pointer operator->() const{// return pointer to class objectreturn (&**this);}_Myt& operator++(){// preincrement++(*(_Mybase *)this);return (*this);}_Myt operator++(int){// postincrement_Myt _Tmp = *this;++*this;return (_Tmp);}_Myt& operator--(){// predecrement--(*(_Mybase *)this);return (*this);}_Myt operator--(int){// postdecrement_Myt _Tmp = *this;--*this;return (_Tmp);}_Myt& operator+=(difference_type _Off){// increment by integer(*(_Mybase *)this) += _Off;return (*this);}_Myt operator+(difference_type _Off) const{// return this + integer_Myt _Tmp = *this;return (_Tmp += _Off);}_Myt& operator-=(difference_type _Off){// decrement by integerreturn (*this += -_Off);}_Myt operator-(difference_type _Off) const{// return this - integer_Myt _Tmp = *this;return (_Tmp -= _Off);}difference_type operator-(const _Mybase& _Right) const{// return difference of iteratorsreturn (*(_Mybase *)this - _Right);}reference operator[](difference_type _Off) const{// subscriptreturn (*(*this + _Off));}
根據上面的源碼樣本,我們很容易看到:
首碼++(--)與尾碼++(--)
1、a++
函數返回:temp(臨時變數)
函數返回是否是const類型:返回是一個拷貝後的臨時變數),不能出現在等號的左邊(臨時變數不能做左值),函數的結果只能做右值,則要返回一個const類型的值
++a
函數返回:*this;
函數返回是否是const類型:返回原狀態的本身,傳回值可以做左值,即函數的結果可以做左值,則要返回一個非const類型的值
2、前尾碼僅從函數名(operator++)無法區分,只能有參數區分,這裡引入一個虛參數int x,x可以是任意整數。
3、單目運算子的重載:
重載運算子函數名:operator@(參數表)
隱式調用形式:obj1@ 或 @obj1
顯式調用形式:
成員函數:
obj1.operator@( )//首碼
obj1.operator@(0)//尾碼
友元函數:
operator@(OBJ obj)//首碼
operator@(OBJ obj,int x)//尾碼
執行時,隱式調用形式和顯式調用形式都會調用函數operator@()
給出樣本出下:
#include <iostream>using namespace std;class Point { private: int x; public: Point(int x1){ x=x1;} Point& operator++();//成員函數定義自增Point operator++(int x); //尾碼可以返回一個const類型的值//Point& operator--();//成員函數定義自增//Point operator--(int x); //尾碼可以返回一個const類型的值friend Point& operator--(Point& p);//友元函數定義--friend Point operator--(Point& p,int x);//尾碼可以返回一個const類型的值friend ostream& operator<<(ostream&out,const Point& p ){out<<p.x;return out ;}}; Point& Point::operator++()//++obj{x++;return *this;}Point Point::operator++(int x)//obj++{Point temp = *this;this->x++;return temp;}Point& operator--(Point& p)//--obj{p.x--;return p;//首碼形式(--obj)重載的時候沒有虛參,通過引用返回*this 或 自身引用,也就是返回變化之後的數值}Point operator--(Point& p,int x)//obj--{Point temp = p;p.x--;return temp;// 尾碼形式obj--重載的時候有一個int類型的虛參, 返回原狀態的拷貝}int main(){Point a(1);Point b(2);a++;//隱式調用成員函數operator++(0),尾碼運算式++a;//隱式調用成員函數operator++(),首碼運算式b--;//隱式調用友元函數operator--(0),尾碼運算式--b;//隱式調用友元函數operator--(),首碼運算式cout<<a.operator ++(2);//顯式調用成員函數operator ++(2),尾碼運算式cout<<a.operator ++();//顯式調用成員函數operator ++(),首碼運算式cout<<operator --(b,2);//顯式調用友元函數operator --(2),尾碼運算式cout<<operator --(b);//顯式調用友元函數operator --(),首碼運算式 </pre>return 0;}
重載輸入輸出操作符<< >>(另外再強調一下這個)
重載方式:只能使用友元函數重載 且 使用三個引用&
函數名:
輸出資料流: operator<<(參數表)
輸入資料流:operator>>(參數表)
參數表:固定(容易出錯啊),兩個參數均用引用&
輸出資料流: 必須是兩個參數:對輸出資料流ostream& 和 對象
第一個運算元cout,定義在檔案iostream中,是標準類類型ostream的對象的引用。
如:ostream& cout,const Point& p
輸入資料流:必須是兩個參數:對輸入資料流ostream& 和 對象
第一個運算元是cin,定義在檔案iostream,實際上是標準類類型istream的對象的引用
如:instream& cin,const Point& p
函數調用:
輸出資料流: 顯式調用:cout<<對象
隱式調用: operator<<(cout,對象)
輸入資料流:顯式調用:cin>>對象
隱式調用: operator>>(cin,對象)
傳回型別:傳回型別固定 + 使用返回函數引用(滿足連續輸出)
輸出資料流: 返回ostream&
如:ostream& operator<<(ostream& cout,const Point& p)
輸入資料流:返回:istream&
如:istream& operator>>(istream& cin,Point& p)
注意:為什麼輸入輸出操作符的重載必須使用友元函數?
因為:成員函數要求是有對象調用,則第一個參數必須是類的對象,但是<<和>>第一個參數是流的對象引用。故,不能使用成員函數
範例程式碼如下:
class ABC{int data ;public:ABC(int d):data(90){}friend ostream&operator<<(ostream&out,const ABC &o) ;friend istream& operator >>(istream & in, ABC &i);};ostream &operator<<(ostream&out,const ABC &o){out<<o.data;return out ;}istream &operator>>(istream& in, ABC &i){in>>i.data ;return in;}
部分內容參考:http://blog.csdn.net/insistgogo/article/details/6626952