C++重載的奧義之運算符重載詳解
0、引言
重載,顧名思義從字面上理解就是重復裝載,打一個不恰當?shù)谋确?,你可以用一個籃子裝蔬菜,也可以裝水果或者其它,使用的是同一個籃子,但是可以用籃子重復裝載的東西不一樣。
正如在之前的文章《重載的奧義之函數(shù)重載》中介紹的類似,函數(shù)的重載是指利用相同的函數(shù)名設計一系列功能相近,但是功能細節(jié)不一樣的函數(shù)接口;因此運算符重載也是指對于同一個運算符來說,它可以用于實現(xiàn)不同的功能。下面就一起來理解下運算符重載的應用。
1、運算符重載定義
正常來說,我們一般使用的運算符是對基本的數(shù)據(jù)類型進行操作,但是在C++中有了對象,導致對象無法通過運算符進行運算,故引入了運算符重載即需要重新的定義這些運算符,賦予已有運算符新的功能,使它能夠用于特定類型執(zhí)行特定的操作。運算符重載的實質是函數(shù)重載,它提供了C++的可擴展性。
運算符重載是通過創(chuàng)建運算符函數(shù)實現(xiàn)的,運算符函數(shù)定義了重載的運算符將要進行的操作。運算符函數(shù)的定義與其他函數(shù)的定義類似,唯一的區(qū)別是運算符函數(shù)的函數(shù)名是由關鍵字operator和其后要重載的運算符符號構成的。運算符函數(shù)定義的一般格式如下:
<返回類型說明符> operator <運算符符號>(<參數(shù)表>)
{
<函數(shù)體>
}
其中,“返回類型說明符”指出重載運算符的返回值類型,operator是定義運算符重載函數(shù)的關鍵字,“運算符符號”指出要重載的運算符名字,是C++中可重載的運算符,比如要重載加法運算符,這里直接寫“+”即可,“參數(shù)表”指出重載運算符所需要的參數(shù)及其類型??梢钥闯觯\算符重載是一種形式C++多態(tài)的體現(xiàn)。
例如,使用“+”將兩個對象相加,編譯器將根據(jù)操作數(shù)的數(shù)目和類型決定使用哪種加法定義,這樣可以讓代碼看起來更加自然。
//正常情況下兩個數(shù)組的數(shù)相加 for(int i= 0; i<10; i++) c[i] = a[i] + b[i]; //可以通過定義一個數(shù)組的類,重載“+”運算符后 //隱藏了內部機制,并強調了實質 arry operator+(arry p,arry q) { arry t; for(int i= 0; i<10; i++) //c = a + b; { t.a[i]=p.a[i]+q.a[i]; } return t; }
運算符重載就是對已有的運算符重新進行定義,賦予其另一種功能,以達到適應不同的數(shù)據(jù)類型。運算符重載不能改變它本來的寓意(也就是加法不能變更為減法),運算符重載只是一種 “語法上的方便” ,它只是一種函數(shù)調用的方式。
2、作為成員函數(shù)進行重載
我們就以“+”運算符重載舉例:
#include <iostream> using namespace std; class addfloat { public: addfloat(float p); //聲明運算符重載 addfloat operator+(const addfloat &A) const; void show() const; private: float m_p; }; addfloat::addfloat(float p) { m_p = p; } //作為類的成員函數(shù)實現(xiàn)運算符重載 addfloat addfloat::operator+(const addfloat &A) const { addfloat B; B.m_p = this->m_p + A.m_p; return B; } void addfloat::show() const { cout<<"輸出結果是"<<m_p<<endl; } int main() { addfloat m(5.1); addfloat n(1.5); addfloat t; t = m + n; //兩個addfloat類對象相加:t = m.operator+(n); t.show(); return 0; }
運行結果為:
輸出結果是6.6
從上面的例子可以看出,在addfloat類中對“+”運算符進行了重載 ,重載后可以對該類的對象進行加法運算。當運行 t = m + n時,編譯器檢測到“+”左邊的m(“+”具有左結合性,所以先檢測左邊)是一個 addfloat類對象,就會調用成員函數(shù) operator+(),將表達式轉換成如下格式:
t = m.operator + (n);
表達式中m作為調用函數(shù)的對象,n作為函數(shù)的實參。
3、作為全局函數(shù)進行重載
對于之前的例子:t = m + n,m和n是作為addfloat類的對象進行相加的,使用成員函數(shù) operator+()轉換為了t = m.operator+(n),如果n不是類的對象,而是一個常數(shù),例如:
t = m + 5.2;那么可以轉換t = m.operator+(5.2);
但是如果m是一個常數(shù)時,即:t = 5.2 + n;則t = (5.2).operator + (n)這種轉換是不允許的,編譯器會報錯,因為5.2不能作為類的對象調用運算符重載operator+()函數(shù)。
這種場景下針對“+”這種運算符作為類的成員函數(shù)進行重載是不可以的。運算符重載不僅僅可以通過類的成員函數(shù)來實現(xiàn),也可以通過全局函數(shù)來實現(xiàn)。
我們需要將運算符重載的全局函數(shù)聲明為友元函數(shù),因為大多數(shù)時候重載運算符要訪問類的私有數(shù)據(jù),(當然也可以設置為非友元非類的成員函數(shù),但是非友元又不是類的成員函數(shù),是沒有辦法直接訪問類的私有數(shù)據(jù)的),如果不聲明為類的友元函數(shù),而是通過在此函數(shù)中調用類的公有函數(shù)來訪問私有數(shù)據(jù)會降低性能。所以一般都會設置為類的友元函數(shù),這樣我們就可以在此非成員函數(shù)中訪問類中的數(shù)據(jù)了。
#include <iostream> using namespace std; class addfloat { public: addfloat(float p); //聲明為友元函數(shù) friend addfloat operator+(const addfloat &A, const addfloat &B); void show() const; private: float m_p; }; addfloat::addfloat(float p) { m_p = p; } void addfloat::show() const { cout<<"輸出結果是"<<m_p<<endl; } //作為全局函數(shù)進行重載 addfloat operator+(const addfloat &A, const addfloat &B) { addfloat C; C.m_p = A.m_p + B.m_p; return C; } int main() { addfloat m(5.1); addfloat n(1.5); addfloat t; t = m + n; //兩個addfloat類對象相加:t = m.operator+(n); t.show(); return 0; }
由上述程序可以看出,運算符重載函數(shù)operator+()不是 addfloat類的成員函數(shù),但是卻用到了 addfloat類的 private 成員變量m_p,所以需要在 addfloat類中將operator+()函數(shù)聲明為友元函數(shù)。
當運行t = m + n時,編譯器檢測到“+”兩邊都是addfloat類的對象,就會轉換為類似下面的函數(shù)調用:
t = operator + (m, n);
因此,m和n都可以看作是函數(shù)的實參:
t = m + 5.2轉換為 t = operator + (m, 5.2);
t = 5.2 + n轉換為 t = operator + (5.2, n);
以全局函數(shù)的形式重載“+”,是為了保證“+”運算符的操作數(shù)能夠被對稱的處理;換句話說,常數(shù)在“+”左邊和右邊都是正確的;
因此,運算符左右兩邊都有操作對象時,且這兩個操作對象可以互換,最好可以使用全局函數(shù)的形式重載,例如:+、-、*、/、==、!= ,這些符合運算符兩邊有操作對象的運算符。
4、運算符重載的一些規(guī)則
(1)可以重載的運算符?
(2)不可以重載的運算符
. (成員訪問運算符)
.* (成員指針訪問運算符)
:: (域運算符)
sizeof (長度運算符)
?: (條件運算符)
(3) 只能以成員函數(shù)的形式重載的運算符(與 this關聯(lián)太多)
= (賦值運算符)
() (函數(shù)調用運算符)
[] (下標運算符)
-> (成員訪問運算符)
(4)只能以全局函數(shù)重載的運算符
<< (左移運算符)
>> (右移運算符)
(5)運算符重載函數(shù)既可以作為類的成員函數(shù),也可以作為全局函數(shù)。友元函數(shù)運算符重載函數(shù)與成員運算符重載函數(shù)的區(qū)別是:友元函數(shù)沒有this指針,而成員函數(shù)有,因此,在兩個操作數(shù)的重載中友元函數(shù)有兩個參數(shù),而成員函數(shù)只有一個。
(6)有一部分運算符重載既可以是成員函數(shù)也可以是全局函數(shù),雖然沒有一個必然的、不可抗拒的理由選擇成員函數(shù),但我們應該優(yōu)先考慮成員函數(shù),這樣更符合運算符重載的初衷。
(7)對于復合的賦值運算符如 +=、-=、*=、/=、&=、!=、~=、%=、>>=、<<= 建議重載為成員函數(shù);
單目運算符最好重載為成員函數(shù);
對于其它運算符,建議重載為全局函數(shù)。
(8)使用運算符不能違反運算符原來的語法規(guī)則,原來有幾個操作數(shù)、操作數(shù)在左邊還是在右邊,這些都不會改變。算符重載函數(shù)不能有默認的參數(shù),否則就改變了運算符操作數(shù)的個數(shù)。
(9)運算符的優(yōu)先級不能被重載改變。然而,圓括號能夠強制改變表達式中重載運算符的求值順序。
(10)運算符的結合性不能被重載改變。如果一個運算符的結合性是從左向右,那么,它的所有重載的版本的結合性依然是從左向右
(11)不能創(chuàng)造新的運算符,即只能重載現(xiàn)有的運算符。例如不能定義operator** (···)來表示求冪。
(12)重載的運算符必須和用戶定義的對象一起使用,運算符參數(shù)(操作的對象)中至少應有一個是類對象(或類對象的引用)。
以上就是C++重載的奧義之運算符重載詳解的詳細內容,更多關于C++運算符重載的資料請關注腳本之家其它相關文章!
相關文章
詳解在C++中顯式默認設置的函數(shù)和已刪除的函數(shù)的方法
這篇文章主要介紹了在C++中顯式默認設置的函數(shù)和已刪除的函數(shù)的方法,文中講到了C++11標準中的新特性,需要的朋友可以參考下2016-01-01C++利用easyx圖形庫實現(xiàn)創(chuàng)意天天酷跑小游戲
這篇文章主要為大家詳細介紹了C++如何利用easyx圖形庫實現(xiàn)創(chuàng)意小游戲——天天酷跑,文中的示例代碼講解詳細,快跟隨小編一起了解一下吧2023-03-03