12--C++_運算符重載

C++_運算符重載

  • 什麼是運算符的重載?

                運算符與類結合,產生新的含義。 ios

  • 爲何要引入運算符重載?

              做用:爲了實現類的多態性(多態是指一個函數名有多種含義)程序員

  • 怎麼實現運算符的重載?

                 方式:類的成員函數 或 友元函數(類外的普通函數)數組

  • 規則:不能重載的運算符有.  和 .* 和 ?: 和 ::  和 sizeof 和 typeid
  • 友元函數和成員函數的使用場合:

    通常狀況下,建議一元運算符使用成員函數,二元運算符使用友元函數函數

        一、運算符的操做須要修改類對象的狀態,則使用成員函數。如須要作左值操做數的運算符(如=,+=,++)this

        二、運算時,有數和對象的混合運算時,必須使用友元spa

        三、二元運算符中,第一個操做數爲對象時,必須使用友元函數。如輸入輸出運算符<<和>>.net

具體規則以下:code

 

運算符對象

建議使用blog

全部一元運算符

成員函數

= ( ) [ ]  ->

必須是成員函數

+= -= /= *= ^= &= != %= >>= <<= , 彷佛帶等號的都在這裏了.

成員函數

全部其它二元運算符, 例如: –,+,*,/

友元函數

<< >>

必須是友元函數

 

二. 參數和返回值

     當參數不會被改變,通常按const引用來傳遞(如果使用成員函數重載,函數也爲const).

     對於返回數值的決定:

     1) 若是返回值可能出如今=號左邊, 則只能做爲左值, 返回非const引用。

     2) 若是返回值只能出如今=號右邊, 則只需做爲右值, 返回const型引用或者const型值。

     3) 若是返回值既可能出如今=號左邊或者右邊, 則其返回值須做爲左值, 返回非const引用。

運算符重載舉例:

+和 -運算符的重載:

[cpp]  view plain  copy
 
  1. class Point    
  2. {    
  3. private:    
  4.     int x;   
  5. public:    
  6.     Point(int x1)  
  7.     {   x=x1;}    
  8.     Point(Point& p)     
  9.     {   x=p.x;}  
  10.     const Point operator+(const Point& p);//使用成員函數重載加號運算符  
  11.     friend const Point operator-(const Point& p1,const Point& p2);//使用友元函數重載減號運算符  
  12. };    
  13.   
  14. const Point Point::operator+(const Point& p)  
  15. {  
  16.     return Point(x+p.x);  
  17. }  
  18.   
  19. Point const operator-(const Point& p1,const Point& p2)  
  20. {  
  21.     return Point(p1.x-p2.x);  
  22. }  

調用:

[cpp]  view plain  copy
 
  1. Point a(1);    
  2. Point b(2);  
  3. a+b;  //正確,調用成員函數  
  4. a-b;  //正確,調用友元函數  
  5. a+1;  //正確,先調用類型轉換函數,把1變成對象,以後調用成員函數  
  6. a-1;  //正確,先調用類型轉換函數,把1變成對象,以後調用友元函數  
  7. 1+a;  //錯誤,調用成員函數時,第一個操做數必須是對象,由於第一個操做數還有調用成員函數的功能  
  8. 1-a;  //正確,先類型轉換 後調用友元函數  

     總結:

一、因爲+ -都是出如今=號的右邊,如c=a+b,即會返回一個右值,能夠返回const型值
二、後幾個表達式討論的就是,數和對象混合運算符的狀況,通常出現這種狀況,常使用友元函數

三、雙目運算符的重載:

      重載運算符函數名:operator@(參數表)

      隱式調用形式:obj1+obj2

      顯式調用形式:obj1.operator+(OBJ obj2)---成員函數

                                  operator+(OBJ obj1,OBJ obj2)---友元函數

      執行時,隱式調用形式和顯式調用形式都會調用函數operator+()

++和--運算符的重載:

[cpp]  view plain  copy
 
  1. class Point    
  2. {    
  3. private:    
  4.     int x;   
  5. public:    
  6.     Point(int x1)  
  7.     {   x=x1;}    
  8.     Point operator++();//成員函數定義自增  
  9.     const Point operator++(int x); //後綴能夠返回一個const類型的值  
  10.     friend Point operator--(Point& p);//友元函數定義--  
  11.     friend const Point operator--(Point& p,int x);//後綴能夠返回一個const類型的值  
  12. };    
  13.   
  14. Point Point::operator++()//++obj  
  15. {  
  16.     x++;  
  17.     return *this;  
  18. }  
  19. const Point Point::operator++(int x)//obj++  
  20. {  
  21.     Point temp = *this;  
  22.     this->x++;  
  23.     return temp;  
  24. }  
  25. Point operator--(Point& p)//--obj  
  26. {  
  27.     p.x--;  
  28.     return p;  
  29.          //前綴形式(--obj)重載的時候沒有虛參,經過引用返回*this 或 自身引用,也就是返回變化以後的數值  
  30. }  
  31. const Point operator--(Point& p,int x)//obj--  
  32. {  
  33.     Point temp = p;  
  34.     p.x--;  
  35.     return temp;  
  36.          // 後綴形式obj--重載的時候有一個int類型的虛參, 返回原狀態的拷貝  
  37. }  

函數調用:

[cpp]  view plain  copy
 
  1. <pre class="cpp" name="code">Point a(1);  
  2. Point b(2);  
  3. a++;//隱式調用成員函數operator++(0),後綴表達式  
  4. ++a;//隱式調用成員函數operator++(),前綴表達式  
  5. b--;//隱式調用友元函數operator--(0),後綴表達式  
  6. --b;//隱式調用友元函數operator--(),前綴表達式  
  7. cout<<a.operator ++(2);//顯式調用成員函數operator ++(2),後綴表達式  
  8. cout<<a.operator ++();//顯式調用成員函數operator ++(),前綴表達式  
  9. cout<<operator --(b,2);//顯式調用友元函數operator --(2),後綴表達式  
  10. cout<<operator --(b);//顯式調用友元函數operator --(),前綴表達式 </pre>  

   總結:

一、a++

       函數返回:temp(臨時變量)

       函數返回是不是const類型:返回是一個拷貝後的臨時變量),不能出如今等號的左邊(臨時變量不能作左值),函數的結果只能作右值,則要返回一個const類型的值

      ++a

       函數返回:*this;

      函數返回是不是const類型:返回原狀態的自己,返回值能夠作左值,即函數的結果能夠作左值,則要返回一個非const類型的值

二、先後綴僅從函數名(operator++)沒法區分,只能有參數區分,這裏引入一個虛參數int x,x能夠是任意整數。

三、單目運算符的重載:

      重載運算符函數名:operator@(參數表)

      隱式調用形式:obj1@  或 @obj1

      顯式調用形式:

             成員函數:

                    obj1.operator@( )//前綴

                    obj1.operator@(0)//後綴

             友元函數:

                    operator@(OBJ obj)//前綴

                    operator@(OBJ obj,int x)//後綴

      執行時,隱式調用形式和顯式調用形式都會調用函數operator@()

 重載下標運算符[ ]

[cpp]  view plain  copy
 
  1. class Point    
  2. {    
  3. private:    
  4.     int x[5];   
  5. public:    
  6.     Point()  
  7.     {  
  8.         for (int i=0;i<5;i++)  
  9.         {  
  10.             x[i]=i;  
  11.         }  
  12.     }   
  13.     int& operator[](int y);  
  14. };    
  15. int& Point::operator[](int y)  
  16. {  
  17.     static int t=0;  
  18.     if (y<5)  
  19.     {  
  20.         return x[y];  
  21.     }  
  22.     else  
  23.     {  
  24.         cout<<"下標出界";  
  25.         return t;  
  26.     }     
  27. }  

調用:

[cpp]  view plain  copy
 
  1. Point a;  
  2. for (int i=0;i<10;i++)  
  3. {  
  4.          cout<<a[i]<<endl;//不管i下標是否越界,每當使用a[i]時,都會調用[]的重載  
  5. }  
  6. a[0]=10;  

重載下標運算符[ ]的目的:

          一、對象[x]  相似於 數組名[x],更加符合習慣

          二、能夠對下標越界做出判斷

語法:

        重載方式:只能使用成員函數重載

        函數名:operator[ ](參數表)

        參數表:一個參數,且僅有一個參數,該參數設定了下標值,一般爲整型,可是也能夠爲字符串( 當作下標)。

        函數調用:顯式調用:Obj[arg]-對象[下標]

                              隱式調用:obj.operator[ ](arg)  

        返回類型:

               一、返回函數引用 + 返回成員的實際類型(由程序員根據函數體定義)

               二、由於返回值能夠作左值和右值,應該不使用返回值爲const類型

                     可是,爲了能訪問const對象,下標運算符重載有非const和const兩個版本。(待定寫)

 如:int&  Point::operator[](int y)//爲何使用返回引用:返回的值能夠作左值,也能夠作右值,則必須使用返回引用

 重載運算符( )

[cpp]  view plain  copy
 
  1. class Point    
  2. {    
  3. private:    
  4.     int x;   
  5. public:    
  6.     Point(int x1)  
  7.     {   x=x1;}    
  8.     const int operator()(const Point& p);  
  9. };    
  10.   
  11. const int Point::operator()(const Point& p)  
  12. {  
  13.     return (x+p.x);  
  14. }  
[cpp]  view plain  copy
 
  1. 調用:  
  2. Point a(1);  
  3. Point b(2);  
  4. cout<<a(b);  

重載運算符( )的目的:

          一、對象( )  相似於 函數名(x),更加符合習慣

語法:

        重載方式:只能使用成員函數重載

        重載後還能夠繼續重載

        函數名:operator( )(參數表)

        參數表:參數隨意,具體根據實際狀況而定。

        函數調用:顯式調用:Obj(x)

                            隱式調用:obj.operator( )(x)  

        返回類型:

               一、返回成員的實際類型隨意,具體由程序員根據函數體定義

               二、由於返回值只能作右值,只讀,應該使用返回值爲const類型


重載輸入輸出操做符<< >>

[cpp]  view plain  copy
 
  1. class Point    
  2. {    
  3. private:    
  4.     int x;   
  5. public:    
  6.     Point(int x1)  
  7.     {   x=x1;}   
  8.     friend ostream& operator<<(ostream& cout,const Point& p);//使用友元函數重載<<輸出運算符  
  9.     friend istream& operator>>(istream& cin,Point& p);//使用友元函數重載>>輸出運算符  
  10. };    
  11. ostream& operator<<(ostream& cout,const Point& p)  
  12. {  
  13.     cout<<p.x<<endl;  
  14.     return cout;  
  15. }  
  16. istream& operator>>(istream& cin,Point& p)  
  17. {  
  18.     cin>>p.x;  
  19.     return cin;  
  20. }  
[cpp]  view plain  copy
 
  1. 調用:  
  2. Point a(1);  
  3. Point b(2);  
  4. cin>>a>>b;  
  5. cout<<a<<b<<endl;   

語法:

重載方式:只能使用友元函數重載 且 使用三個引用&

函數名:

       輸出流: 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)

注意:爲何輸入輸出操做符的重載必須使用友元函數?

由於:成員函數要求是有對象調用,則第一個參數必須是類的對象,可是<<和>>第一個參數是流的對象引用。

故,不能使用成員函數

相關文章
相關標籤/搜索