[C++]運算子過載

丫就是熊個貓貓發表於2016-12-13

運算子過載

函式的過載

所謂函式的過載是指完成不同功能的函式可以具有相同的函式名。

C++的編譯器是根據函式的實參來確定應該呼叫哪一個函式的。

int  fun(int a,  int b)

{   return a+b;  }

int  fun (int a)

{   return a*a;  }

void  main(void)

{  cout<<fun(3,5)<<endl;

   cout<<fun(5)<<endl;

}

 

1、定義的過載函式必須具有不同的引數個數,或不同的引數型別。只有這樣編譯系統才有可能根據不同的引數去呼叫不同的過載函式。

2、僅返回值不同時,不能定義為過載函式。

class A

{  float x,y;

public:

    A(float a=0, float b=0){  x=a; y=b; }

}

void main(void)

{  A   a(2,3),  b(3,4),  c;

     c=a+b;          兩物件不能使用+,必須重新定義+

}

運算子過載就是賦予已有的運算子多重含義。C++通過重新定義運算子,使它能夠用於特定類的物件執行特定的功能

運算子的過載從另一個方面體現了OOP技術的多型性,且同一運算子根據不同的運算物件可以完成不同的操作。

為了過載運算子,必須定義一個函式,並告訴編譯器,遇到這個過載運算子就呼叫該函式,由這個函式來完成該運算子應該完成的操作。這種函式稱為運算子過載函式,它通常是類的成員函式或者是友元函式。運算子的運算元通常也應該是類的物件。

 

過載為類的成員函式

格式如下:

<類名>  operator<運算子>(<參數列>)

{函式體}

operator:  關鍵字

參數列:  運算的物件

其中:operator是定義運算子過載函式的關鍵字,它與其後的運算子一起構成函式名。

沒有過載運算子的例子

class A

{int i;

public:A(int a=0){ i=a;}

void Show(void){cout<<"i="<<i<<endl;}

void AddA(A &a,A &b)//利用函式進行類之間的運算  利用函式完成了加法運算

{i=a.i+b.i;}

};

void main(void)

{A a1(10),a2(20),a3;

a1.Show ();

a2.Show ();

//a3=a1+a2;//不可直接運算

a3.AddA(a1,a2);//呼叫專門的功能函式   用和作物件呼叫函式

a3.Show ();

}

 

class A

{int i;

public:A(int a=0){ i=a;}

void Show(void){cout<<"i="<<i<<endl;}

void AddA(A &a,   A &b)//利用函式進行類之間的運算

{i=a.i+b.i;}

A operator +(A &a)//過載運算子+

{A   t;t.i=i+a.i;return t;}

};

void main(void)

{A a1(10),a2(20),a3;

a1.Show ();

a2.Show (); 

a3=a1+a2;//重新解釋了加法,可以直接進行類的運算   相當於a3=a1.operator+(a2)

a3.AddA(a1,a2);//呼叫專門的功能函式

a3.Show ();

}

 

過載運算子與一般函式的比較:

相同:1)均為類的成員函式;2)實現同一功能

 

 

總結:

重新定義運算子,由左操作符呼叫右操作符。最後將函式返回值賦給運算結果的物件。

 

class A

{int i;

public:A(int a=0){ i=a;}

void Show(void){cout<<"i="<<i<<endl;}

void AddA(A &a,   A &b)//利用函式進行類之間的運算

{i=a.i+b.i;}

A operator +(A &a)//過載運算子+

{A   t;t.i=i+a.i;return t;}

};

void main(void)

{A a1(10),a2(20),a3;

a1.Show ();

a2.Show ();

a3=a1+a2;//重新解釋了加法,可以直接進行類的運算

a3.AddA(a1,a2);//呼叫專門的功能函式

a3.Show ();

}

 

當用成員函式實現運算子的過載時,運算子過載函式的引數只能有二種情況:沒有引數或帶有一個引數。對於只有一個運算元的運算子(如++),在過載這種運算子時,通常不能有引數;而對於有二個運算元的運算子,只能帶有一個引數。這引數可以是物件,物件的引用,或其它型別的引數。在C++中不允許過載有三個運算元的運算子

2、在C++中,允許過載的運算子列於表13.1中。

3、在C++中不允許過載的運算子列於表13.2。

4、只能對C++中已定義了的運算子進行過載,而且,當過載一個運算子時,該運算子的優先順序和結合律是不能改變的。

 

單目運算子的過載

只具有一個運算元的運算子為單目運算子,最常用的為++及--。

A    a;

++a;

a++;

 

A    a, b;

b=++a;

b=a++;

可以看出,雖然運算後物件a的值一致,但先自加或後自加的過載運算子函式的返回值不一致,必須在過載時予以區分。

 

++為前置運算時,它的運算子過載函式的一般格式為:

<type> operator ++( )

{    ......;}

++為後置運算時,它的運算子過載函式的一般格式為:

<type>  operator ++(int)

{    ......;}

用成員函式實現運算子的過載時,運算子的左運算元為當前物件,並且要用到隱含的this指標。運算子過載函式不能定義為靜態的成員函式,因為靜態的成員函式中沒有this指標。

 

運算子過載為友元函式

運算子過載為成員函式時,是由一個運算元呼叫另一個運算元。

友元函式是在類外的普通函式,與一般函式的區別是可以呼叫類中的私有或保護資料。

將運算子的過載函式定義為友元函式,參與運算的物件全部成為函式引數。

對雙目運算子,友元函式有2個引數,對單目運算子,友元函式有一個引數。有些運算子不能過載為友元函式,它們是:=,(),[ ],->等

格式為:

friend <型別說明> operator<運算子>(<參數列>)

{......}

c=a+b;   //  c=operator+( a, b)

friend   A   operator + (A &a, A &b)

{.....}

    對雙目運算子,過載為成員函式時,僅一個引數,另一個被隱含;過載為友元函式時,有兩個引數,沒有隱含引數。

    一般來說,單目運算子最好被過載為成員函式;對雙目運算子最好被過載友元函式。

轉換函式

轉換函式就是在類中定義一個成員函式,其作用是將類轉換為某種資料型別。

class  A

{    float x, y;

  public:

    A(float  a, float b){  x=a; y=b;  }

};

void main(void)

{  A   a(2,3);

   cout<<a<<endl;

}

注意,轉換函式只能是成員函式,不能是友元函式。轉換函式的運算元是物件。轉換函式可以被派生類繼承,也可以被說明為虛擬函式。

 

賦值運算子與賦值運算子過載 “=”

同型別的物件間可以相互賦值,等同於物件的各個成員的一一賦值。

但當物件的成員中使用了動態的資料型別時(用new開闢空間),就不能直接相互賦值,否則在程式的執行期間會出現執行錯誤。

 

這時,利用編譯系統的預設賦值無法正確執行程式,必須過載賦值運算子“=”,即重新定義“=”。

格式為:

<函式型別>   <ClassName>::operator=(<參數列>)

賦值運算子必須過載為成員函式。

 

一個字串類

在C++中,系統提供的字串處理能力比較弱,都是通過字元處理函式來實現的,並且不能直接對字串進行加法、減法,字串的拼接,字串之間的相互賦值等操作。可以通過應用C++提供的運算子過載機制,可以提供字串的直接操作能力,使得字串的操作與一般的資料一樣方便。

class String

{     int Length;//字串長度

      char *Sp;  //字串在記憶體中的首地址

 public:

       .....

}

可見,字串類只定義了指標,並沒有開闢具體的空間以存放字串的內容,所以,無論是構造、析構還是加減等,均需要考慮動態開闢空間的問題,這也是字串類的難點。

若不定義字串的解構函式,則可以不定義它的拷貝的構造及賦值函式,若定義了解構函式,必須重新定義這兩個成員函式。

 

相關文章