C 關於運算子過載

2022-05-17 05:50:19 字數 3702 閱讀 3335

過載運算子的函式一般格式如下:

函式型別 operator 運算子名稱 (形參表列)

例如,想將」+」用於complex類(複數)的加法運算,函式的原型可以是這樣的:

complex operator+ (complex& c1, complex& c2);

在上面的一般格式中,operator是關鍵字,是專門用於定義過載運算子的函式的,運算子名稱就是c++提供給使用者的預定義運算子。注意,函式名是由operator和運算子組成,上面的operator+就是函式名,意思是「對運算子+過載」。只要掌握這點,就可以發現,這 類函式和其他函式在形式上沒有什麼區別。兩個形參是complex類物件的引用,要求實參為complex類物件。

在定義了過載運算子的函式後,可以說,函式operator +過載了運算子+。在執行複數相加的表示式c1 + c2時(假設c1和c2都已被定義為complex類物件),系統就會呼叫operator+函式,把c1和c2作為實參,與形參進行虛實結合。

為了說明在運算子過載後,執行表示式就是呼叫函式的過程,可以把兩個整數相加也想像為呼叫下面的函式:

int operator + (int a, int b)

如果有表示式5+8,就呼叫此函式,將5和8作為呼叫函式時的實參,函式的返回值為13。這就是用函式的方法理解運算子。可以在例10.1程式的基礎上過載運算子「+」,使之用於複數相加。

[例10.2] 改寫例10.1,過載運算子「+」,使之能用於兩個複數相加。

#include

using namespace std;

classcomplex

complex(double r,double i)

complexoperator+(complex&c2);//宣告過載運算子的函式

void display( );

private:

double real;

double imag;

};complexcomplex::operator+(complex&c2) //定義過載運算子的函式

void complex::display( )

int main( )

執行結果與例10.1相同:

c1=(3+4i)

c2=(5-10i)

c1+c2=(8,-6i)

請比較例10.1和例10.2,只有兩處不同:

1) 在例10.2中以operator+函式取代了例10.1中的complex_add函式,而且只是函式名不同,函式體和函式返回值的型別都是相同的。

2) 在main函式中,以「c3=c1+c2;」取代了例10.1中的「c3=c1.complex_add(c2);」。在將運算子+過載為類的成員函式後,c++編譯系統將程式中的表示式c1+c2解釋為

c1.operator+(c2)  //其中c1和c2是complex類的物件

即以c2為實參呼叫c1的運算子過載函式operator+(complex &c2),進行求值,得到兩個複數之和。

可以看到,兩個程式的結構和執行過程基本上是相同的,作用相同,執行結果也相同。過載運算子是由相應的函式實現的。有人可能說,既然這樣,何必對運算子過載呢?我們要從使用者的角度來看問題,雖然過載運算子所實現的功能完全可以用函式實現,但是使用運算子過載能使使用者程式易於編寫、閱讀和維護。在實際工作中,類的宣告和類的使用往往是分離的。假如在宣告complex類時,對運算子+, -, *, /都進行了過載,那麼使用這個類的使用者在程式設計時可以完全不考慮函式是怎麼實現的,放心大膽地直接使用+, -, *, /進行複數的運算即可,十分方便。

對上面的運算子過載函式operator+還可以改寫得更簡練一些:

complex complex::operator + (complex &c2)

return語句中的complex( real+c2.real, imag+c2.imag)是建立乙個臨時物件,它沒有對名,是乙個無名物件。在建立臨時物件過程中呼叫建構函式。return語句將此臨時物件作為函式返回值。

請思考,在例10.2中能否將乙個常量和乙個複數物件相加?如

c3=3+c2;  //錯誤,與形參型別不匹配

應寫成物件形式,如

c3 = complex (3,0) +c2;  //正確,型別均為物件

需要說明的是,運算子被過載後,其原有的功能仍然保留,沒有喪失或改變。通過運算子過載,擴大了c++已有運算子的作用範圍,使之能用於類物件。

運算子過載對c++有重要的意義,把運算子過載和類結合起來,可以在c++程式中定義出很有實用意義而使用方便的新的資料型別。運算子過載使c++具有更強大的功能、更好的可擴充性和適應性,這是c++最吸引人的特點之一。

c++對運算子過載定義了如下幾條規則。

1) c++不允許使用者自己定義新的運算子,只能對已有的c++運算子進行過載。 例如,有人覺得basic中用「**「作為冪運算子很方便,也想在c++中將」**「定義為冪運算子,用」3**5「表示35,這樣是不行的。

2) 過載不能改變運算子運算物件(即搡作數)的個數。如關係運算子「>」和「 <」 等是雙目運算子,過載後仍為雙目運算子,需要兩個引數。運算子「 +」,「-」,「*」,「&」等既可以作為單目運算子,也可以作為雙目運算子,可以分別將它們過載為單目運算子或雙目運算子。

3) 過載不能改變運算子的優先級別。例如「*」和「/」優先於「 +」和「-」,不論怎樣進行過載,各運算子之間的優先級別不會改變。有時在程式中希望改變某運算子的優先順序,也只能使用加圓括號的辦法強制改變過載運算子的運算順序。

4) 過載不能改變運算子的結合性。如賦值運算子是右結合性(自右至左),過載後仍為右結合性。

5) 過載運算子的函式不能有預設的引數,否則就改變了運算子引數的個數,與前面第(2)點矛盾。

6) 過載的運算子必須和使用者定義的自定義型別的物件一起使用,其引數至少應有乙個是類物件(或類物件的引用)。也就是說,引數不能全部是c++的標準型別,以防止使用者修改用於標準型別資料的運算子的性質,如下面這樣是不對的:

int operator + (int a,int b)

原來運算子+的作用是對兩個數相加,現在企圖通過過載使它的作用改為兩個數相減。 如果允許這樣過載的話,如果有表示式4+3,它的結果是7呢還是1?顯然,這是絕對禁止的。

如果有兩個引數,這兩個引數可以都是類物件,也可以乙個是類物件,乙個是c ++標準型別的資料,如

complex operator + (int a,complex&c)

它的作用是使乙個整數和乙個複數相加。

7) 用於類物件的運算子一般必須過載,但有兩個例外,運算子「=」和「&」不必過載。

①賦值運算子( = )可以用於每乙個類物件,可以利用它在同類物件之間相互賦值。 我們知道,可以用賦值運算子對類的物件賦值,這是因為系統已為每乙個新宣告的類過載了乙個賦值運算子,它的作用是逐個複製類的資料成員。使用者可以認為它是系統提供的預設的物件賦值運算子,可以直接用於物件間的賦值,不必自己進行過載。但是有時系統提供的預設的物件賦值運算子不能滿足程式的要求,例如,資料成員中包含指向動態分配記憶體的指標成員時,在複製此成員時就可能出現危險。在這種情況下, 就需要自己過載賦值運算子。

②位址運算子&也不必過載,它能返回類物件在記憶體中的起始位址。

8) 從理論上說,可以將乙個運算子過載為執行任意的操作,如可以將加法運算子過載為輸出物件中的資訊,將「>」運算子過載為「小於」運算。但這樣違背了運算子過載的初衷,非但沒有提髙可讀性,反而使人莫名其妙,無法理解程式。應當使過載運算子的功能類似於該運算子作用於標準型別資料時所實現的功能(如用「+」實現加法,用「>」實現「大於」的關係運算)。

9) 運算子過載函式可以是類的成員函式,也可以是類的友元函式,還可以是既非類的成員函式也不是友元函敝的普通函式。

關於運算子過載

之前看 effective c 的時候,對這一部分印象比較深刻,雖然讀的時候有寫筆記,但是現在還是寫下來我對這一部分理解。詳細的內容可以看條款19 分清成員函式,非成員函式和友元。條款19的結論如下 只有在下列情況下,讓函式f成為類c的非成員函式。其餘情況,f都宣告為c的成員函式。1 operato...

關於運算子過載

所謂運算子過載其實就是對於運算子針對不同操作物件而實現不同功能,其實質就是函式過載 函式過載前面有一篇介紹 實現過程就是先把運算表示式轉化為對運算子函式的呼叫,把運算物件轉化為運算函式的實參,然後根據實參的型別確定需要呼叫的函式。另外,c 標準規定了一些不能過載的操作符,分別是 1.類屬關係運算子 ...

C 運算子過載 過載特殊運算子

賦值運算子用於同類物件間的相互賦值。賦值運算子只能被過載為類的非靜態成員函式,不能過載為友元函式和普通函式。對於使用者自定義的類而言,如果沒有過載賦值運算子,那麼c 編譯器會為該類提供乙個預設的過載賦值運算子成員函式。預設賦值運算子的工作方式是按位對拷,將等到右邊物件的非靜態成員拷貝給等號左邊的物件...