81

我讀過一個聲明爲成員函數的重載運算符是不對稱的,因爲它只能有一個參數,而另一個自動傳遞的參數是'this'指針。所以沒有標準來比較它們。另一方面,被聲明爲朋友的重載運算符是對稱的,因爲我們傳遞了兩個相同類型的參數,因此可以進行比較。 我的問題是,當我仍然可以比較一個指針的左值與引用時,爲什麼朋友更喜歡? (使用非對稱版本會得到與對稱版本相同的結果) 爲什麼STL算法只使用對稱版本?運算符重載:成員函數與非成員函數?

+9

你的問題實在是隻有約二元運算符。並非所有重載操作符都被限制爲單個參數。 ()運算符可以接受任意數量的參數。另一方面,一元運算符不能有任何參數。 – 2011-01-07 04:16:23

+1

http://stackoverflow.com/a/4421729/103167 – 2012-02-19 01:09:23

+2

這是[C++ FAQ:運算符重載]中涵蓋的許多主題之一(http://stackoverflow.com/questions/4421706/operator-overloading) – 2012-02-19 01:09:37

回答

101

如果您將運算符重載函數定義爲成員函數,那麼編譯器會將表達式s1 + s2轉換爲s1.operator+(s2)這意味着,運算符重載的成員函數會在第一個操作數上被調用。這就是成員函數的工作方式!

但是如果第一個操作數不是類呢? 如果我們想要在第一個操作數不是類的類型時重載操作符,那麼存在一個主要問題,而不是類型double所以你不能這樣寫10.0 + s2。但是,您可以編寫運算符重載成員函數,用於表達式如s1 + 10.0

爲了解決這個訂購問題,我們定義操作重載功能friend如果需要訪問private成員。 只有當它需要訪問私人成員時才使它成爲friend否則乾脆就讓它非朋友非會員功能改進封裝!

class Sample 
{ 
public: 
    Sample operator + (const Sample& op2); //works with s1 + s2 
    Sample operator + (double op2); //works with s1 + 10.0 

    //Make it `friend` only when it needs to access private members. 
    //Otherwise simply make it **non-friend non-member** function. 
    friend Sample operator + (double op1, const Sample& op2); //works with 10.0 + s2 
} 

閱讀這些:
A slight problem of ordering in operands
How Non-Member Functions Improve Encapsulation

14

這不一定friend運算符重載和成員函數運算符重載,因爲它是全球運算符重載和成員函數運算符重載之間的區別。

一個理由,更喜歡一個全球運算符重載是,如果你想允許式,其類類型的二元運算符的右手邊出現。例如:

Foo f = 100; 
int x = 10; 
cout << x + f; 

這隻能如果存在用於

富操作者+(INT X,常量富& F)一個全球運營商超載;

請注意,全局運算符過載不一定需要是friend函數。這僅在需要訪問Foo的私人成員時纔有必要,但情況並非總是如此。

無論如何,如果Foo只有一個成員函數運算符重載,如:

class Foo 
{ 
    ... 
    Foo operator + (int x); 
    ... 
}; 

...那麼我們只能夠在那裏一個Foo實例上似乎有表情離開的加運營商。