C 運算子過載的三個為什麼

2021-08-24 17:33:48 字數 1503 閱讀 7108

四個不能宜載為友元函式的運算子為:=、()、、->

我在網上搜了許多部落格,很多人都說是:

當把賦值運算子過載為類的友員函式,在程式中執行類物件的賦值語句時,程式就會出現兩種矛盾的選擇。

(1)因為它認為類中並沒有過載賦值運算子的成員函式,所以它根據c++的規則,會去呼叫相應的建構函式。

(2)但是在全域性裡,我們已經過載了引數型別為此類型別的賦值運算子函式,而這賦值語句剛好和這函式匹配上了,根據c++的規則,也會去呼叫這函式。

程式是不允許有矛盾不確定選擇的,所以當賦值運算子過載為類的友元函式時,編譯器就會提示錯誤。

對於剩下的3個運算子 ->, , () 為什麼不能過載為友元函式,也是跟上面一樣的道理。即編譯器發現當類中沒有定義這3個運算子的過載成員函式時,就會自己加入預設的運算子過載成員函式。

然而,上面的解釋是有問題的。它的大概意思就是因為編譯器對上述四個操作符有預設的運算子過載成員函式。在這種情況下若是使用者把上述四個運算子過載為類的友元函式,則會引起編譯器不知道用預設的還是用友元過載,所以會出錯。

但是在c++中的六個預設的成員函式當中並沒有()、和->,所以編譯器並不會對()、和->產生預設的運算子過載成員函式

按照我的理解:

c++對運算子過載有如下要求:

1. 不能改變運算子運算元的個數

2. 不能改變運算子原有的優先順序

3. 不能改變運算子原有的結合性

4. 不能改變操作符原有的語法結構

四個運算子=、()、、->它們的語法結構為:運算子左側必須為乙個變數或者物件。若是過載為類的成員函式正好符合這一點;但是若過載為類的友元函式,則可能會這樣一種情況:過載時在形參列表中調換了兩個引數的順序,導致形參列表中的第乙個引數不是要呼叫該運算子的變數或者物件,就對改變了操作符原有的語法結構。所以編譯器會報錯。

如果是過載雙目操作符(即為類的成員函式),就只要設定乙個引數作為右側運算量,而左側運算量就是物件本身。而 >> 或<< 左側運算量是 cin或cout 而不是物件本身,所以不滿足後面一點,就只能申明為友元函式了。

如果過載為類的成員函式,在呼叫時必然會出現這種情況:cout << object;, 在編譯器編譯時就會解釋為:cout.opreator <<(class & object);。這明顯是錯誤的。

另外,大部份的標準庫實現中,對ostream,istream類體系採用了建構函式保護繼承的方式。致使即使以繼承的方式來擴充套件流類,也會在物件例項化時遭遇阻礙。

另一方面,標準庫中的流類,其插入符函式沒有宣告為虛函式,因此子類不能對其實現進行覆蓋,所以也使成員函式過載遭遇到實質的困難。

四個不能過載的操作符為:.、.*、::、?:、sizeof

前兩個運算子不能過載是為了保證訪問成員的功能不能被改變,域運算符合sizeof運算子的運算物件是型別而不是變數或一般表示式,不具備過載的特徵。

C 運算子過載(三)

前面介紹了運算子過載有兩種實現方法 成員函式和友元函式 一句話總結 當兩種方法都能實現運算子過載時,請使用成員函式這種方式實現,忘了友元函式。那麼友元函式的出現是為了解決什麼難題的?友元函式總結 1.為什麼有友元函式?在實現類之間資料共享時,減少系統開銷,提高效率。下面兩種情況需要使用友元函式 1 ...

擴充套件運算子 三個點( )

含義 擴充套件運算子 spread 是三個點 將乙個陣列轉為用逗號分隔的引數序列。運算元組 裡面放自己定義的方法 methods 在陣列中新增元素 iclick3 在陣列中刪除元素 取出乙個元素 與結構賦值的結合 如果將擴充套件運算子用於陣列賦值,只能放在引數的最後一位,否則會報錯。iclick8 ...

運算子的三個層次理解

第一層理解 當運算元都是布林值時,運算子對兩個值執行布林與 and 操作,只有第乙個運算元和第二個運算元都是true,它才返回true。例如 x 0 y 0 只有在x和y都是0,才返回true 第二層理解 可以對真值和假值進行布林與 and 運算。把 符號左側和右側的表示式或者 資料型別轉為布林值。...