day6 6 1運算子過載及過載規則

2021-10-04 11:05:21 字數 4576 閱讀 6748

所謂過載,就是賦予新的含義。函式過載(function overloading)可以讓乙個函式名有多種功能,在不同情況下進行不同的操作。運算子過載(operator overloading)也是乙個道理,同乙個運算子可以有不同的功能。

實際上,我們已經在不知不覺中使用了運算子過載。例如,+號可以對不同型別(int、float 等)的資料進行加法操作;<<既是位移運算子,又可以配合 cout 向控制台輸出資料。c++ 本身已經對這些運算子進行了過載。

c++ 也允許程式設計師自己過載運算子,這給我們帶來了很大的便利。下面看一下自己實現複數類的「+」過載例子

//實現複數類的 + 運算子過載

#include

using

namespace std;

class

complex

complex

(double real,

double image)

;private

:double m_real;

double m_image;

public

://過載運算子

complex operator+(

const complex &e)

const

;void

display()

}; complex::

complex

(double real,

double image)

//有參建構函式

//成員函式運算子過載

定義:運算子過載其實就是定義乙個函式,在函式體內實現想要的功能,當用到該運算子時,編譯器會自動呼叫這個函式。也就是說,運算子過載是通過函式實現的,它本質上是函式過載。

運算子過載的格式為:

返回值型別 operator 運算子名稱 (形參表列)

operator是關鍵字,專門用於定義過載運算子的函式。我們可以將operator 運算子名稱這一部分看做函式名,對於上面的**,函式名就是operator+

運算子過載函式除了函式名有特定的格式,其它地方和普通函式並沒有區別。

上面的例子中,我們在 complex 類中過載了運算子+,該過載只對 complex 物件有效。當執行c3 = c1 + c2;語句時,編譯器檢測到+號左邊(+號具有左結合性,所以先檢測左邊)是乙個 complex 物件,就會呼叫成員函式operator+(),也就是轉換為下面的形式:

c3 = c1.

operator

+(c2)

;//把operator+當作函式,就變成傳入引數c2,計算了。

//c1 是要呼叫函式的物件,c2 是函式的實參。c3是返回值

上面的運算子過載還可以有更加簡練的定義形式:

complex complex::

operator+(

const complex &a)

const

return 語句中的complex(this->m_real + a.m_real, this->m_imag + a.m_imag)會建立乙個臨時物件,這個物件沒有名稱,是乙個匿名物件。在建立臨時物件過程中呼叫建構函式,return 語句將該臨時物件作為函式返回值。

運算子過載函式不僅可以作為類的成員函式,還可以作為全域性函式。更改上面的**,在全域性範圍內過載+,實現複數的加法運算:

//實現複數類的運算子過載

#include

using

namespace std;

class

complex

complex

(double real,

double image)

;private

:double m_real;

double m_image;

public

://過載運算子,使用友元函式

friend complex operator+(

const complex &a,

const complex &b)

;void

display()

}; complex::

complex

(double real,

double image)

//有參建構函式

//使用友元函式運算子過載

complex operator+(

const complex &a,

const complex &b)

intmain()

運算子過載函式不是 complex 類的成員函式,但是卻用到了 complex 類的 private 成員變數,所以必須在 complex 類中將該函式宣告為友元函式

當執行c3 = c1 + c2;語句時,編譯器檢測到+號兩邊都是 complex 物件,就會轉換為類似下面的函式呼叫:

c3 =

operator

+(c1, c2)

;

運算子過載是通過函式過載實現的,概念上大家都很容易理解。但是規則挺多。

1)並不是所有的運算子都可以過載。能夠過載的運算子包括:

+-*

/%^&

|~!=

<

>+=

-=*=

/=%=

^=&=

|=<<

>>

<<=

>>=

==!=

<=

>=

&&||

++--,-

>*-

>()

newnew

delete

delete

上述運算子中,是下標運算子,()是函式呼叫運算子。自增自減運算子的前置和後置形式都可以過載。長度運算子sizeof、條件運算子: ?、成員選擇符.和域解析運算子::不能被過載。

2)過載不能改變運算子的優先順序和結合性。假設上面的 complex 類中過載了+號和*號,並且 c1、c2、c3、c4 都是 complex 類的物件,那麼下面的語句:

c4 = c1 + c2 * c3;
等價於:

c4 = c1 +

( c2 * c3 )

;

乘法的優先順序仍然高於加法,並且它們仍然是二元運算子。

3)過載不會改變運算子的用法,原有幾個運算元、運算元在左邊還是在右邊,這些都不會改變。例如~號右邊只有乙個運算元,+號總是出現在兩個運算元之間,過載後也必須如此。

4)運算子過載函式不能有預設的引數,否則就改變了運算子運算元的個數,這顯然是錯誤的

5)運算子過載函式既可以作為類的成員函式,也可以作為全域性函式。

運算子過載函式作為類的成員函式時,二元運算子的引數只有乙個,一元運算子不需要引數。之所以少乙個引數,是因為這個引數是隱含的。

例如,上面的 complex 類中過載了加法運算子:

complex operator+(const complex & a) const;

當執行:

c3 = c1 + c2;

會被轉換為:

c3 = c1.

operator

+(c2)

;

通過 this 指標隱式的訪問 c1 的成員變數。

運算子過載函式作為全域性函式時,二元操作符就需要兩個引數,一元操作符需要乙個引數,而且其中必須有乙個引數是物件,好讓編譯器區分這是程式設計師自定義的運算子,防止程式設計師修改用於內建型別的運算子的性質。

例如,下面這樣是不對的:

int

operator+(

int a,

int b)

如果有兩個引數,這兩個引數可以都是物件,也可以乙個是物件,乙個是c ++內建型別的資料,例如:

complex operator+(

int a, complex &c)

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

6)箭頭運算子->、下標運算子[ ]、函式呼叫運算子( )、賦值運算子=只能以成員函式的形式過載。

運算子過載之過載型別運算子

普通型別 類型別 呼叫對應的只有乙個引數 引數的型別就是這個普通型別 的建構函式 需求 boy boy1 10000 薪資 建構函式boy int boy boy2 rock 姓名 建構函式boy char 普通型別賦值給類型別其實很簡單,就是專門的對這個賦值的型別定義乙個建構函式。編譯器在執行 的...

運算子過載 賦值運算子的過載

有時候希望賦值運算子兩邊的型別可以不匹配,比如,把乙個int型別變數賦值給乙個complex物件,或把乙個 char 型別的字串賦值給乙個字串物件,此時就需要過載賦值運算子 注意 賦值運算子 只能過載為成員函式 賦值運算子過載例項示例 include include using namespace ...

過載之運算子過載

運算子過載,就是對已有的運算子重新進行定義,賦予其另一種功能,以適應不同的資料型別 運算子過載的宣告方式與方法的宣告方式相同,但operator關鍵字告訴編譯器,它實際上是乙個運算子過載,後面是相關運算子的符號,在本例中就是 返回型別是在使用這個運算子時獲得的型別。在本例中,把兩個向量加起來會得到另...