C++類(lèi)和對(duì)象之運(yùn)算符重載解讀
C++ 運(yùn)算符重載
一、什么是運(yùn)算符重載?
運(yùn)算符重載是 C++ 的一種特性,它允許程序員為自定義類(lèi)型(如類(lèi)和結(jié)構(gòu)體)重新定義運(yùn)算符的行為。通過(guò)運(yùn)算符重載,我們可以使用熟悉的運(yùn)算符語(yǔ)法來(lái)操作自定義類(lèi)型的對(duì)象,從而使代碼更加簡(jiǎn)潔、直觀。
當(dāng)運(yùn)算符被?于類(lèi)類(lèi)型的對(duì)象時(shí),C++語(yǔ)?允許我們通過(guò)運(yùn)算符重載的形式指定新的含義。C++規(guī)定類(lèi)類(lèi)型對(duì)象使?運(yùn)算符時(shí),必須轉(zhuǎn)換成調(diào)?對(duì)應(yīng)運(yùn)算符重載,若沒(méi)有對(duì)應(yīng)的運(yùn)算符重載,則會(huì)編譯報(bào)錯(cuò)。
例如,我們可以為自定義的復(fù)數(shù)類(lèi)重載 +
運(yùn)算符,使得兩個(gè)復(fù)數(shù)對(duì)象可以直接使用 +
進(jìn)行相加:
Complex a(1, 2); Complex b(3, 4); Complex c = a + b; // 使用重載的 + 運(yùn)算符
二、運(yùn)算符重載的語(yǔ)法規(guī)則
在 C++ 中,運(yùn)算符重載通過(guò)定義特殊的成員函數(shù)或非成員函數(shù)來(lái)實(shí)現(xiàn)。
其基本語(yǔ)法如下:
返回類(lèi)型 operator運(yùn)算符(參數(shù)列表) { // 函數(shù)體 }
其中:
operator
是 C++ 的關(guān)鍵字,用于聲明一個(gè)運(yùn)算符重載函數(shù)。- 運(yùn)算符 是要重載的運(yùn)算符,如
+
,-
,*
,/
等。 - 返回類(lèi)型 是運(yùn)算符重載函數(shù)的返回值類(lèi)型,通常與操作數(shù)的類(lèi)型相關(guān)。
- 參數(shù)列表 是運(yùn)算符重載函數(shù)的參數(shù),參數(shù)的個(gè)數(shù)和類(lèi)型取決于運(yùn)算符的種類(lèi)和重載方式。
注意:
- ?個(gè)類(lèi)需要重載哪些運(yùn)算符,是看哪些運(yùn)算符重載后有意義
- 重載++運(yùn)算符時(shí),有前置++和后置++,運(yùn)算符重載函數(shù)名都是operator++,?法很好的區(qū)分。C++規(guī)定,后置++重載時(shí),增加?個(gè)int形參,跟前置++構(gòu)成函數(shù)重載,?便區(qū)分。
- 當(dāng)運(yùn)算符被?于類(lèi)類(lèi)型的對(duì)象時(shí),C++語(yǔ)?允許我們通過(guò)運(yùn)算符重載的形式指定新的含義。C++規(guī)定類(lèi)類(lèi)型對(duì)象使?運(yùn)算符時(shí),必須轉(zhuǎn)換成調(diào)?對(duì)應(yīng)運(yùn)算符重載,若沒(méi)有對(duì)應(yīng)的運(yùn)算符重載,則會(huì)編譯報(bào)錯(cuò)。
- 運(yùn)算符重載是具有特殊名字的函數(shù),他的名字是由operator和后?要定義的運(yùn)算符共同構(gòu)成。和其他函數(shù)?樣,它也具有其返回類(lèi)型和參數(shù)列表以及函數(shù)體。
- 重載運(yùn)算符函數(shù)的參數(shù)個(gè)數(shù)和該運(yùn)算符作?的運(yùn)算對(duì)象數(shù)量?樣多。?元運(yùn)算符有?個(gè)參數(shù),?元運(yùn)算符有兩個(gè)參數(shù),?元運(yùn)算符的左側(cè)運(yùn)算對(duì)象傳給第?個(gè)參數(shù),右側(cè)運(yùn)算對(duì)象傳給第?個(gè)參數(shù)。
- 如果?個(gè)重載運(yùn)算符函數(shù)是成員函數(shù),則它的第?個(gè)運(yùn)算對(duì)象默認(rèn)傳給隱式的this指針,因此運(yùn)算符重載作為成員函數(shù)時(shí),參數(shù)?運(yùn)算對(duì)象少?個(gè)。
- 運(yùn)算符重載以后,其優(yōu)先級(jí)和結(jié)合性與對(duì)應(yīng)的內(nèi)置類(lèi)型運(yùn)算符保持?致。
- 不能通過(guò)連接語(yǔ)法中沒(méi)有的符號(hào)來(lái)創(chuàng)建新的操作符:?如operator@。
重載<<和>>時(shí),需要重載為全局函數(shù),因?yàn)橹剌d為成員函數(shù),this指針默認(rèn)搶占了第?個(gè)形參位置,第?個(gè)形參位置是左側(cè)運(yùn)算對(duì)象,調(diào)?時(shí)就變成了 對(duì)象<<cout,不符合使?習(xí)慣和可讀性。
重載為全局函數(shù)把ostream/istream放到第?個(gè)形參位置就可以了,第?個(gè)形參位置當(dāng)類(lèi)類(lèi)型對(duì)象。
成員函數(shù)重載
運(yùn)算符重載函數(shù)可以作為類(lèi)的成員函數(shù)來(lái)定義。在這種情況下,函數(shù)的參數(shù)個(gè)數(shù)比運(yùn)算符的操作數(shù)少一個(gè),因?yàn)榈谝粋€(gè)操作數(shù)是通過(guò) this
指針隱式傳遞的。
非成員函數(shù)重載
運(yùn)算符重載函數(shù)也可以作為非成員函數(shù)(全局函數(shù)或友元函數(shù))來(lái)定義。
在這種情況下,函數(shù)的參數(shù)個(gè)數(shù)與運(yùn)算符的操作數(shù)相同。
賦值運(yùn)算符重載
賦值運(yùn)算符重載是?個(gè)默認(rèn)成員函數(shù),?于完成兩個(gè)已經(jīng)存在的對(duì)象直接的拷?賦值,這?要注意跟拷?構(gòu)造區(qū)分,拷?構(gòu)造?于?個(gè)對(duì)象拷?初始化給另?個(gè)要?jiǎng)?chuàng)建的對(duì)象。
賦值運(yùn)算符重載的特點(diǎn):
- 賦值運(yùn)算符重載是?個(gè)運(yùn)算符重載,規(guī)定必須重載為成員函數(shù)。賦值運(yùn)算重載的參數(shù)建議寫(xiě)成const當(dāng)前類(lèi)類(lèi)型引?,否則會(huì)傳值傳參會(huì)有拷?
- 有返回值,且建議寫(xiě)成當(dāng)前類(lèi)類(lèi)型引?,引?返回可以提?效率,有返回值?的是為了?持連續(xù)賦值場(chǎng)景。
- 沒(méi)有顯式實(shí)現(xiàn)時(shí),編譯器會(huì)?動(dòng)?成?個(gè)默認(rèn)賦值運(yùn)算符重載,默認(rèn)賦值運(yùn)算符重載?為跟默認(rèn)拷?構(gòu)造函數(shù)類(lèi)似,對(duì)內(nèi)置類(lèi)型成員變量會(huì)完成值拷?/淺拷?(?個(gè)字節(jié)?個(gè)字節(jié)的拷?),對(duì)?定義類(lèi)型成員變量會(huì)調(diào)?他的賦值重載函數(shù)。
拷貝構(gòu)造:一個(gè)存在的對(duì)象去初始化另一個(gè)要實(shí)例化的對(duì)象; 賦值重載:已存在的兩個(gè)對(duì)象之間的拷貝,注意返回值為類(lèi)類(lèi)型,處理連續(xù)賦值的情況
取地址運(yùn)算符重載
const成員函數(shù)
- 將const修飾的成員函數(shù)稱(chēng)之為const成員函數(shù),const修飾成員函數(shù)放到成員函數(shù)參數(shù)列表的后?。
- const實(shí)際修飾該成員函數(shù)隱含的this指針,表明在該成員函數(shù)中不能對(duì)類(lèi)的任何成員進(jìn)?修改。Date* const this 變?yōu)?const Date* const this
取地址運(yùn)算符重載
- 取地址運(yùn)算符重載分為普通取地址運(yùn)算符重載和const取地址運(yùn)算符重載,?般這兩個(gè)函數(shù)編譯器?動(dòng)?成的就可以夠我們?了,不需要去顯?實(shí)現(xiàn)。
- 除??些很特殊的場(chǎng)景,?如我們不想讓別?取到當(dāng)前類(lèi)對(duì)象的地址,就可以??實(shí)現(xiàn)?份,胡亂返回?個(gè)地址。
三、可重載的運(yùn)算符和不可重載的運(yùn)算符
可重載的運(yùn)算符
C++ 中大部分運(yùn)算符都可以被重載,包括:
- 算術(shù)運(yùn)算符:
+
,-
,*
,/
,%
,++
,--
- 比較運(yùn)算符:
==
,!=
,<
,>
,<=
,>=
- 邏輯運(yùn)算符:
&&
,||
,!
- 位運(yùn)算符:
&
,|
,^
,~
,<<
,>>
- 賦值運(yùn)算符:
=
,+=
,-=
,*=
,/=
,%=
,&=
,|=
,^=
,<<=
,>>=
- 其他運(yùn)算符:
[]
,()
,->
,,
,*
(解引用),&
(取地址)
不可重載的運(yùn)算符
C++ 中少數(shù)運(yùn)算符不能被重載,包括:
- 作用域解析運(yùn)算符:
::
- 成員訪問(wèn)運(yùn)算符:
.
和.*
- 條件運(yùn)算符:
?:
- 類(lèi)型轉(zhuǎn)換運(yùn)算符:
typeid
和dynamic_cast
等 - 編譯時(shí)運(yùn)算符:
sizeof
五、運(yùn)算符重載的注意事項(xiàng)
在使用運(yùn)算符重載時(shí),需要注意以下幾點(diǎn):
- 遵循運(yùn)算符的原有語(yǔ)義:運(yùn)算符重載應(yīng)該保持運(yùn)算符原有的語(yǔ)義,避免造成混淆。例如,重載
+
運(yùn)算符應(yīng)該實(shí)現(xiàn)加法的語(yǔ)義,而不是減法。 - 不要濫用運(yùn)算符重載:雖然運(yùn)算符重載可以使代碼更加簡(jiǎn)潔,但過(guò)度使用或?yàn)E用會(huì)使代碼變得難以理解和維護(hù)。
- 保持運(yùn)算符的優(yōu)先級(jí)和結(jié)合性:運(yùn)算符重載不能改變運(yùn)算符的優(yōu)先級(jí)和結(jié)合性,這是由語(yǔ)言規(guī)定的。
- 正確處理 const 對(duì)象:如果運(yùn)算符重載函數(shù)不修改對(duì)象的狀態(tài),應(yīng)該將其聲明為
const
成員函數(shù)。 - 注意內(nèi)存管理:在重載賦值運(yùn)算符和拷貝構(gòu)造函數(shù)時(shí),需要特別注意深拷貝和淺拷貝的問(wèn)題,避免內(nèi)存泄漏。
- 避免創(chuàng)建新的運(yùn)算符:C++ 不允許創(chuàng)建新的運(yùn)算符,只能重載已有的運(yùn)算符。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
C++中map和vector作形參時(shí)如何給定默認(rèn)參數(shù)?
今天小編就為大家分享一篇關(guān)于C++中map和vector作形參時(shí)如何給定默認(rèn)參數(shù)?,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-04-04C++深入學(xué)習(xí)之徹底理清重載函數(shù)匹配
C++ 不允許變量重名,但是允許多個(gè)函數(shù)取相同的名字,只要參數(shù)表不同即可,這叫作函數(shù)的重載,下面這篇文章主要給大家介紹了關(guān)于C++深入學(xué)習(xí)之徹底理清重載函數(shù)匹配的相關(guān)資料,需要的朋友可以參考下2019-01-01C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)的時(shí)間復(fù)雜度和空間復(fù)雜度
算法在編寫(xiě)成可執(zhí)行程序后,運(yùn)行時(shí)需要耗費(fèi)時(shí)間資源和空間(內(nèi)存)資源 。因此衡量一個(gè)算法的好壞,一般是從時(shí)間和空間兩個(gè)維度來(lái)衡量的,即時(shí)間復(fù)雜度和空間復(fù)雜度,感興趣的同學(xué)可以參考閱讀2023-04-04Qt6.0開(kāi)發(fā)環(huán)境搭建步驟(圖文)
這篇文章主要介紹了Qt6.0開(kāi)發(fā)環(huán)境搭建步驟(圖文),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03OpenCV實(shí)現(xiàn)車(chē)牌定位(C++)
這篇文章主要為大家詳細(xì)介紹了OpenCV實(shí)現(xiàn)車(chē)牌定位,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-11-11C++ LeetCode1812判斷國(guó)際象棋棋盤(pán)格子顏色
這篇文章主要為大家介紹了C++ LeetCode1812判斷國(guó)際象棋棋盤(pán)格子顏色, 有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12