重載運算符

原文: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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章