C++操作符重載專題

 C++操作符重載專題
  一、爲什麼使用操作符重載?
  對於系統的所有操作符,一般情況下,只支持基本數據類型和標準庫中提供的class,對於用戶自己定義的class,如果想支持基本操作,比如比較大小,判斷是否相等,等等,則需要用戶自己來定義關於這個操作符的具體實現。比如,判斷兩個人是否一樣大,我們默認的規則是按照其年齡來比較,所以,在設計person 這個class的時候,我們需要考慮操作符==,而且,根據剛纔的分析,比較的依據應該是age。那麼爲什麼叫重載呢?這是因爲,在編譯器實現的時候,已經爲我們提供了這個操作符的基本數據類型實現版本,但是現在他的操作數變成了用戶定義的數據類型class,所以,需要用戶自己來提供該參數版本的實現。
  二、如何聲明一個重載的操作符?
  A:操作符重載實現爲類成員函數
  重載的操作符在類體中被聲明,聲明方式如同普通成員函數一樣,只不過他的名字包含關鍵字operator,以及緊跟其後的一個c++預定義的操作符。
  可以用如下的方式來聲明一個預定義的==操作符:
  class person{
  private:
  int age;
   public:
   person(int a){
  this->age=a;
  }
  inline bool operator ==(const person &ps) const;
  };
  實現方式如下:
  inline bool person::operator==(const person &ps) const
  { if (this->age==ps.age)
   return true;
  return false;
  }
  調用方式如下:
   #include
  using namespace std;
  int main()
  { person p1(10);
  person p2(20);
  if(p1==p2) cout<<”the age is equal!”<  return 0;
  }
  這裏,因爲operator ==是class person的一個成員函數,所以對象p1,p2都可以調用該函數,上面的if語句中,相當於p1調用函數==,把p2作爲該函數的一個參數傳遞給該函數,從而實現了兩個對象的比較。
  考慮如下的if語句:
   if(10==p1) cout<<”the age is equal!”<  是否回正確執行呢?
  答案是不會的,因爲只有左操作數是該類類型的對象的時,纔會考慮作爲類成員重載操作符。因爲10不是person類型的對象,所以,不能調用classperson的操作符==。
  考慮如下if語句:
  if(person(10)==person(11))
   cout<<"ok"<  是否能夠正確執行呢?答案是可以,因爲操作符兩邊均是無名對象。
  重載的操作符並不要求兩個操作數的類型一定相同。例如:我們可以爲class person定義下標操作符,以表示該person和電話的對應關係:
  /*實現下標操作符*/
  #include
  #include
  using namespace std;
  class person
  { private:
   int tel;
  public:
  int & operator[](string const & nm)
  {
   return tel;
  }
  int GetTel()
  {
  return tel;
  }
  };
  int main()
  {
  person p1;
  p1["suo"]=110;
  person p2;
  p2["rose"]=120;
  cout<  cout<  return 0;
  }
  對於重載爲成員函數方式的操作符,隱式的this指針被作爲該函數的第一個參數,來代表左操作數。
  B:操作符重載實現爲非類成員函數(全局函數)
  對於全局重載操作符,代表左操作數的參數必須被顯式指定。例如:
  #include
  #include
  using namespace std;
  class person
  {
  public:
   int age;
  public:
  };
  /*在類的外部,不能訪問該類私有數據,所以,要把
  age設置爲public*/
  bool operator==(person const &p1 ,person const & p2)
  {
   if(p1.age==p2.age)
   return true;
   return false;
  }
  int main()
  {
  person rose;
  person jack;
  rose.age=18;
  jack.age=23;
  if(rose==jack)/*兩個對象分別代表左右操作數*/
  cout<<"ok"<  return 0;
  }
  C:如何決定把一個操作符重載爲類成員函數還是全局名字空間的成員呢?
  ①如果一個重載操作符是類成員,那麼只有當與他一起使用的左操作數是該類的對象時,該操作符纔會被調用。如果該操作符的左操作數必須是其他的類型,則操作符必須被重載爲全局名字空間的成員。
  ②C++要求賦值=,下標[],調用(), 和成員指向-> 操作符必須被定義爲類成員操作符。任何把這些操作符定義爲名字空間成員的定義都會被標記爲編譯時刻錯誤。
  ③如果有一個操作數是類類型如string類的情形那麼對於對稱操作符比如等於操作符最好定義爲全局名字空間成員。
  D:操作符重載爲友元函數方式
   如果把操作符重載爲友元函數方式,則在該函數的內部,可以直接訪問授權類的私有數據成員,這是友元函數方式和全局名字空間方式的主要區別。
  E:怎樣判斷一個非類成員的操作符應該是類的友元還是應該使用成員訪問函數呢?一般來說,類的實現者應該儘量使得名字空間函數和訪問類內部表示的操作符的數目最小化。如果已經提供了訪問成員函數並且它們具有等同的效率,那麼最好是使用這些成員函數。但是如果類的實現者決定不爲該類的某些私有成員提供訪問成員函數而且名字空間操作符需要引用這些私有成員才能完成,它們的操作那麼就必須使用友元機制。
   例如:
  #include
  #include
  using namespace std;
  class person{
  public:
   int age;
  public:
  };
  
  
  
  
  
  
  bool operator==(person const &p1 ,person const & p2)
  {
  if(p1.age==p2.age) return true;
  return false;
  }
  ostream operator<<(ostream &os,person const &p)
  {
  os<<"the person age is:"<  return os;
  }
  int main()
  {
  person rose;
  person jack;
  rose.age=18;
  jack.age=23;
  cout<  /*call ostream operator<<(ostream &os,person const &p) */
  cout<  return 0;
  }
  三、重載操作符的設計
  ①類的設計者不能聲明一個沒有預定義的重載操作符。
  ②不能爲內置數據類型定義其他的操作符。
  ③預定義的操作符優先級不能被改變。
  ④一個類最終需要提供哪些操作符,是由該類預期的用途來決定的。
  四、prefix and postfix
   爲區分後置操作符與前置操作符的聲明,重載的遞增和遞減後置操作符的聲明有一個額外的int 類型的參數。這裏不需要給出參數名,因爲它沒有被用在操作符定義中。額外的整型參數對於後置操作符的用戶是透明的,編譯器爲它提供了缺省值因而該參數也可以被忽略。
  例如:
  #include
  #include
  using namespace std;
  class person
  {
  private:
   int age;
  public:
   person(int a)
   {
   age=a;
   }
  person const operator++()/*prefix ++ */
  {
   this->age++;
   return *this;
  }
  person const operator++(int a)/*postfix ++ */
  {
   person temp(1);
   temp=*this;
   this->age++;
   return temp;
  }
  int GetAge()
  {
   return age;
  }
  };
  int main()
  {
  person rose(10);
  person jack(20);
  person marry(22);
  person tom(30);
  jack=++rose;
  marry= tom++;
  cout<  cout<  return 0;
  }
 
發佈了71 篇原創文章 · 獲贊 0 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章