先上題:下列運(yùn)算符都可以被友元函數(shù)重載的是:
A) =,+,-,
B) [],+,(),new
C) ->,+,,>>
D) <<,>>,+,
正確答案為D
在運(yùn)算符重載示惊,友元函數(shù)運(yùn)算符重載函數(shù)與成員運(yùn)算符重載函數(shù)的區(qū)別是:友元函數(shù)沒有this指針逐虚,而成員函數(shù)有汰瘫,因此迎膜,在兩個(gè)操作數(shù)的重載中友元函數(shù)有兩個(gè)參數(shù)敌呈,而成員函數(shù)只有一個(gè)。
重載運(yùn)算符的基本原則:
- 為了防止用戶對(duì)標(biāo)準(zhǔn)類型進(jìn)行運(yùn)算符重載鞋仍,C++規(guī)定重載后的運(yùn)算符的操作對(duì)象必須至少有一個(gè)是用戶定義的類型
比如說現(xiàn)在有兩個(gè)數(shù):int number1,int number2常摧,
那么number1+number2 求的是兩個(gè)數(shù)的和,
但是如果你重載以后讓著兩個(gè)數(shù)相加為他們的乘積威创,這肯定是不合乎邏輯的落午。
可能重載以后會(huì)有二義性,導(dǎo)致程序不知道該執(zhí)行哪一個(gè)(是自帶的的還是重載后的函數(shù)) - 使用運(yùn)算符不能違法運(yùn)算符原來的句法規(guī)則。如不能將% 重載為一個(gè)操作數(shù)
- 不能修改運(yùn)算符原先的優(yōu)先級(jí)
- 不能創(chuàng)建一個(gè)新的運(yùn)算符肚豺,例如不能定義operator** (···)來表示求冪
-
不能進(jìn)行重載的運(yùn)算符:
.:成員訪問運(yùn)算符
., ->:成員指針訪問運(yùn)算符
:::域運(yùn)算符
sizeof:長度運(yùn)算符
?::條件運(yùn)算符
#: 預(yù)處理符號(hào)
下面比較成員函數(shù)和非成員函數(shù)(友元函數(shù))重載運(yùn)算符
- 對(duì)雙目運(yùn)算符而言板甘,成員函數(shù)重載運(yùn)算符的函數(shù)參數(shù)表中只有一個(gè)參數(shù),而用友元函數(shù)重載運(yùn)算符函數(shù)參數(shù)表中含有兩個(gè)參數(shù)详炬。
對(duì)單目運(yùn)算符來說,成員函數(shù)重載運(yùn)算符的函數(shù)參數(shù)表中沒有參數(shù)寞奸,而用友元函數(shù)重載運(yùn)算符函數(shù)參數(shù)表中含有一個(gè)函數(shù)呛谜。這個(gè)問題要搞清楚,有一個(gè)this指針的問題 - 雙目運(yùn)算符一般可以用友元函數(shù)重載和成員函數(shù)重載枪萄,但有一種情況只可以用友元函數(shù)重載隐岛。
即:雙目運(yùn)算符左邊的變量是一個(gè)常量,而不是對(duì)象4煞>郯肌!這點(diǎn)很重要的額齐帚。比如說string妒牙,左邊是一個(gè)const char*
string str = "test";
string ok = "testtest" + str;
//這樣的運(yùn)算符必須是友元,因?yàn)樗牡谝粋€(gè)參數(shù)是char* 類型对妄,相當(dāng)于調(diào)用 operator (char , string str)
string oook = str + "testset"; //這個(gè)就必須是成員函數(shù)湘今,因?yàn)榈谝粋€(gè)str+ 表示調(diào)用str的成員函數(shù)operator+(char )
所以說,單目運(yùn)算符建議選擇成員函數(shù)剪菱。
下面是重點(diǎn)
只能作為成員函數(shù)重載的四個(gè)操作符
=摩瞎,(),[]孝常,->
原因很簡(jiǎn)單旗们,會(huì)和編譯器默認(rèn)分配的運(yùn)算符重載成員函數(shù)沖突,引發(fā)歧義构灸。
我們知道友元函數(shù)不是類的成員函數(shù)上渴,它只是類的“朋友“,具有訪問把它聲明為“朋友”的類的數(shù)據(jù)成員的權(quán)限而已。
那么當(dāng)把賦值運(yùn)算符重載為類的友員函數(shù)驰贷,在程序中執(zhí)行類對(duì)象的賦值語句時(shí)盛嘿,程序就會(huì)出現(xiàn)兩種矛盾的選擇。
- 因?yàn)樗J(rèn)為類中并沒有重載賦值運(yùn)算符的成員函數(shù)括袒,所以它根據(jù)C++的規(guī)則次兆,會(huì)去調(diào)用相應(yīng)的構(gòu)造函數(shù)。
- 但是在全局里锹锰,我們已經(jīng)重載了參數(shù)類型為此類類型的賦值運(yùn)算符函數(shù)芥炭,而這賦值語句剛好和這函數(shù)匹配上了,根據(jù)C++的規(guī)則恃慧,也會(huì)去調(diào)用這函數(shù)园蝠。
程序是不允許有矛盾不確定選擇的,所以當(dāng)賦值運(yùn)算符重載為類的友元函數(shù)時(shí)痢士,編譯器就會(huì)提示錯(cuò)誤彪薛。
對(duì)于剩下的3個(gè)運(yùn)算符 ->, [], () 為什么不能重載為友元函數(shù),也是跟上面一樣的道理怠蹂。即編譯器發(fā)現(xiàn)當(dāng)類中沒有定義這3個(gè)運(yùn)算符的重載成員函數(shù)時(shí)善延,就會(huì)自己加入默認(rèn)的運(yùn)算符重載成員函數(shù)。
那么下面這個(gè)題的答案也就很明顯了:
將x+y*z中的“+”用成員函數(shù)重載城侧,“*”用友元函數(shù)重載應(yīng)該寫為:易遣?
答案為:x.operator+(operator*(y,z))