所謂過載,就是賦予新的含義。函式過載(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關鍵字告訴編譯器,它實際上是乙個運算子過載,後面是相關運算子的符號,在本例中就是 返回型別是在使用這個運算子時獲得的型別。在本例中,把兩個向量加起來會得到另...