C/C++對bool operator < (const p &a)const的認識,運算符重載詳解(雜談)

下面來進行這段代碼的分析:

struct node {  //定義一個結構體node(節點)

   int x;

   int y;

   int len;   //node中有3個成員變量x,y,len

   bool operator <(const node &a)const {//重載<操做符。能夠對兩個node使用<操做符進行比較

       return len<a.len;

   }

};

括號中的const表示參數a對象不會被修改,最後的const代表調用函數對象不會被修改!

想必看到這裏對重載運算符算是有一丁點的瞭解吧,下面看些理論文字,更加清楚的瞭解關係!node

重載運算符的介紹

C++中預約義的運算符的操做對象只能是基本數據類型。但實際上,對於許多用戶自定義類型(例如類),也須要相似的運算操做。這時就必須在C++中從新定義這些運算符,賦予已有運算符新的功能,使它可以用於特定類型執行特定的操做。運算符重載的實質是函數重載,它提供了C++的可擴展性,也是C++最吸引人的特性之一。 
  運算符重載是經過建立運算符函數實現的,運算符函數定義了重載的運算符將要進行的操做。運算符函數的定義與其餘函數的定義相似,唯一的區別是運算符函數的函數名是由關鍵字operator和其後要重載的運算符符號構成的。運算符函數定義的通常格式以下:

 

   

<返回類型說明符> operator <運算符符號>(<參數表>) {      <函數體> }

 

 運算符重載時要遵循如下規則:函數

(1) 除了類屬關係運算符"."、成員指針運算符".*"、做用域運算符"::"、sizeof運算符和三目運算符"?:"之外,C++中的全部運算符均可以重載。 (2) 重載運算符限制在C++語言中已有的運算符範圍內的容許重載的運算符之中,不能建立新的運算符。 (3) 運算符重載實質上是函數重載,所以編譯程序對運算符重載的選擇,遵循函數重載的選擇原則。 (4) 重載以後的運算符不能改變運算符的優先級和結合性,也不能改變運算符操做數的個數及語法結構。 (5) 運算符重載不能改變該運算符用於內部類型對象的含義。它只能和用戶自定義類型的對象一塊兒使用,或者用於用戶自定義類型的對象和內部類型的對象混合使用時。 (6) 運算符重載是針對新類型數據的實際須要對原有運算符進行的適當的改造,重載的功能應當與原有功能相相似,避免沒有目的地使用重載運算符。
  運算符函數重載通常有兩種形式:重載爲類的成員函數和重載爲類的非成員函數。非成員函數一般是友元。(能夠把一個運算符做爲一個非成員、非友元函數重載。可是,這樣的運算符函數訪問類的私有和保護成員時,必須使用類的公有接口中提供的設置數據和讀取數據的函數,調用這些函數時會下降性能。能夠內聯這些函數以提升性能。)   

成員函數運算符性能

 運算符重載爲類的成員函數的通常格式爲:     <函數類型> operator <運算符>(<參數表>)     {      <函數體>     }

  當運算符重載爲類的成員函數時,函數的參數個數比原來的操做數要少一個(後置單目運算符除外),這是由於成員函數用this指針隱式地訪問了類的一個對象,它充當了運算符函數最左邊的操做數。所以:this

(1) 雙目運算符重載爲類的成員函數時,函數只顯式說明一個參數,該形參是運算符的右操做數。 (2) 前置單目運算符重載爲類的成員函數時,不須要顯式說明參數,即函數沒有形參。 (3) 後置單目運算符重載爲類的成員函數時,函數要帶有一個整型形參。     調用成員函數運算符的格式以下:     <對象名>.operator <運算符>(<參數>)     它等價於     <對象名><運算符><參數>     例如:a+b等價於a.operator +(b)。通常狀況下,咱們採用運算符的習慣表達方式。

友元函數運算符spa

 運算符重載爲類的友元函數的通常格式爲:     friend <函數類型> operator <運算符>(<參數表>)     {      <函數體>     }

  當運算符重載爲類的友元函數時,因爲沒有隱含的this指針,所以操做數的個數沒有變化,全部的操做數都必須經過函數的形參進行傳遞,函數的參數與操做數自左至右一一對應。指針

 調用友元函數運算符的格式以下:     operator <運算符>(<參數1>,<參數2>)     它等價於     <參數1><運算符><參數2>     例如:a+b等價於operator +(a,b)。

兩種重載形式的比較code

  在多數狀況下,將運算符重載爲類的成員函數和類的友元函數都是能夠的。但成員函數運算符與友元函數運算符也具備各自的一些特色:對象

(1) 通常狀況下,單目運算符最好重載爲類的成員函數;雙目運算符則最好重載爲類的友元函數。 (2) 如下一些雙目運算符不能重載爲類的友元函數:=、()、[]、->。 (3) 類型轉換函數只能定義爲一個類的成員函數而不能定義爲類的友元函數。 (4) 若一個運算符的操做須要修改對象的狀態,選擇重載爲成員函數較好。 (5) 若運算符所需的操做數(尤爲是第一個操做數)但願有隱式類型轉換,則只能選用友元函數。 (6) 當運算符函數是一個成員函數時,最左邊的操做數(或者只有最左邊的操做數)必須是運算符類的一 個類對象(或者是對該類對象的引用)。若是左邊的操做數必須是一個不一樣類的對象,或者是一個內部 類型的對象,該運算符函數必須做爲一個友元函數來實現。 (7) 當須要重載運算符具備可交換性時,選擇重載爲友元函數。

下面具體講講重載運算符的一些具體用法吧!

1.通常運算符重載

在進行對象之間的運算時,程序會調用與運算符相對應的函數進行處理,因此運算符重載有兩種方式:成員函數和友元函數。成員函數的形式比較簡單,就是在類裏面定義了一個與操做符相關的函數。友元函數由於沒有this指針,因此形參會多一個。blog

 1     class A
 2     {
 3     public:
 4      A(int d):data(d){}
 5      A operator+(A&);//成員函數
 6      A operator-(A&);
 7      A operator*(A&);
 8      A operator/(A&);
 9      A operator%(A&);
10      friend A operator+(A&,A&);//友元函數
11      friend A operator-(A&,A&);
12      friend A operator*(A&,A&);
13      friend A operator/(A&,A&);
14      friend A operator%(A&,A&);
15     private:
16      int data;
17     };
18     //成員函數的形式
19     A A::operator+(A &a)
20     {
21      return A(data+a.data);
22     }
23     A A::operator-(A &a)
24     {
25      return A(data-a.data);
26     }
27     A A::operator*(A &a)
28     {
29      return A(data*a.data);
30     }
31     A A::operator/(A &a)
32     {
33      return A(data/a.data);
34     }
35     A A::operator%(A &a)
36     {
37      return A(data%a.data);
38     }
39     //友元函數的形式
40     A operator+(A &a1,A &a2)
41     {
42      return A(a1.data+a2.data);
43     }
44     A operator-(A &a1,A &a2)
45     {
46      return A(a1.data-a2.data);
47     }
48     A operator*(A &a1,A &a2)
49     {
50      return A(a1.data*a2.data);
51     }
52     A operator/(A &a1,A &a2)
53     {
54      return A(a1.data/a2.data);
55     }
56     A operator%(A &a1,A &a2)
57     {
58      return A(a1.data%a2.data);
59     }
60     //而後咱們就能夠對類的對象進行+、-、*、/了。
61     void main(void)
62     {
63      A a1(1),a2(2),a3(3);
64      a1=a2+a3;
65      //或者
66      a1=a2.operator+(a3);
67     }

注意:在進行a2+a3的時候會出錯,由於咱們在上面對+定義了兩種方法,去掉一種便可。接口

2.關係運算符重載

由於函數體比較簡單,後面我就只給出成員函數形式的函數聲明瞭,關係運算符有==,!=,<,>,<=,>=。

1     bool operator == (const A& ); 
2     bool operator != (const A& );
3     bool operator < (const A& );
4     bool operator <= (const A& );
5     bool operator > (const A& );
6     bool operator >= (const A& );

3.邏輯運算符重載

1     bool operator || (const A& );
2     bool operator && (const A& );
3     bool operator ! ();

4.單目運算符重載

這裏的+、-是正負的意思,放在對象前面。

1     A& operator + ();
2     A& operator - ();
3     A* operator & ();
4     A& operator * ();

5.自增減運算符重載

++和–根據位置的不一樣有四種狀況,均可以重載。

1     A& operator ++ ();//前置++
2     A operator ++ (int);//後置++
3     A& operator --();//前置--
4     A operator -- (int);//後置--

6.位運算符重載

按位操做。

1     A operator | (const A& );
2     A operator & (const A& );
3     A operator ^ (const A& );
4     A operator << (int i);
5     A operator >> (int i);
6     A operator ~ ();

7.賦值運算符重載

沒有=哦。

 1     A& operator += (const A& );
 2     A& operator -= (const A& ); 
 3     A& operator *= (const A& );
 4     A& operator /= (const A& );
 5     A& operator %= (const A& );
 6     A& operator &= (const A& );
 7     A& operator |= (const A& );
 8     A& operator ^= (const A& );
 9     A& operator <<= (int i);
10     A& operator >>= (int i);

8.內存運算符重載

1     void *operator new(size_t size);
2     void *operator new(size_t size, int i);
3     void *operator new[](size_t size);
4     void operator delete(void*p);
5     void operator delete(void*p, int i, int j);
6     void operator delete [](void* p);

9.特殊運算符重載

上面的運算符重載都有兩種方式,而下面的運算符只能用一種,特殊吧。 這些運算符的重載只能是成員函數。

 1     A& operator = (const A& );
 2     char operator [] (int i);//返回值不能做爲左值
 3     const char* operator () ();
 4     T operator -> ();
 5     //類型轉換符
 6     operator char* () const;
 7     operator int ();
 8     operator const char () const;
 9     operator short int () const;
10     operator long long () const;
11     //還有不少就不寫了

而這些只能以友元函數的形式重載

1     friend inline ostream &operator << (ostream&, A&);//輸出流
2     friend inline istream &operator >> (istream&, A&);//輸入流

10.總結

兩種重載方式的比較:

  • 通常狀況下,單目運算符最好重載爲類的成員函數;雙目運算符則最好重載爲類的友元函數。
  • 如下一些雙目運算符不能重載爲類的友元函數:=、()、[]、->。
  • 類型轉換函數只能定義爲一個類的成員函數而不能定義爲類的友元函數。 C++提供4個類型轉換函數:reinterpret_cast(在編譯期間實現轉換)、const_cast(在編譯期間實現轉換)、stactic_cast(在編譯期間實現轉換)、dynamic_cast(在運行期間實現轉換,並能夠返回轉換成功與否的標誌)。
  • 若一個運算符的操做須要修改對象的狀態,選擇重載爲成員函數較好。
  • 若運算符所需的操做數(尤爲是第一個操做數)但願有隱式類型轉換,則只能選用友元函數。
  • 當運算符函數是一個成員函數時,最左邊的操做數(或者只有最左邊的操做數)必須是運算符類的一個類對象(或者是對該類對象的引用)。若是左邊的操做數必須是一個不一樣類的對象,或者是一個內部 類型的對象,該運算符函數必須做爲一個友元函數來實現。
  • 當須要重載運算符具備可交換性時,選擇重載爲友元函數。

注意事項:

  1. 除了類屬關係運算符」.「、成員指針運算符」.*「、做用域運算符」::「、sizeof運算符和三目運算符」?:「之外,C++中的全部運算符均可以重載。
  2. 重載運算符限制在C++語言中已有的運算符範圍內的容許重載的運算符之中,不能建立新的運算符。
  3. 運算符重載實質上是函數重載,所以編譯程序對運算符重載的選擇,遵循函數重載的選擇原則。
  4. 重載以後的運算符不能改變運算符的優先級和結合性,也不能改變運算符操做數的個數及語法結構。
  5. 運算符重載不能改變該運算符用於內部類型對象的含義。它只能和用戶自定義類型的對象一塊兒使用,或者用於用戶自定義類型的對象和內部類型的對象混合使用時。
  6. 運算符重載是針對新類型數據的實際須要對原有運算符進行的適當的改造,重載的功能應當與原有功能相相似,避免沒有目的地使用重載運算符。
相關文章
相關標籤/搜索