2012-05-13 115 views
0

將運算符重載作爲成員和非成員函數的想法非常混淆。作爲成員函數和非成員函數的運算符函數

當我們將運算符重載爲非成員函數時,我們的實際意思是什麼,以及當我們將運算符重載爲成員函數時,我們的意思是什麼。雖然我知道非會員功能是朋友的功能。

+1

非會員「運營商」不一定是「朋友」。 – robert

+0

您不必非非會員運營商的朋友,如果您不需要,您不應該這樣做。 – chris

+0

[重載操作符作爲成員函數或非成員(朋友)函數的可能重複?](http://stackoverflow.com/questions/1905439/overload-operators-as-member-function-or-non-member-friend函數) –

回答

1

如果您將運算符重載爲非成員函數,則需要在參數列表中明確指定要對其進行操作的對象。

如果您將其作爲成員函數重載,則「this」指針將爲您完成部分工作。

請看下面的例子:

class Test { 
    public: 
    friend Test operator+(const Test &lhs, const Test &rhs); // Non-member function 
    Test operator+(const Test &rhs); // Member function 
}; 

兩者的區別在於,非成員函數沒有this指針編譯器方便地傳遞給你,只要你是在談論一個特定實例一類。

成員函數有一個lhs推斷,因此你只需要提供rhs。

請注意,「朋友」不是必需的,但如果您想訪問Test的私人會員,則需要它。

編譯器可以基於參數計數來消除歧義。如果你想聲明friend Test operator+(const Test &rhs),它會抱怨論證不足,因爲+是一個二元運算符。成員函數操作符+的lhs是「this」。

0

例如

class Foo { 
public: 
    Foo operator+(Foo) // member variant 
    // declared inside the function 
}; // end of class 

Foo operator+(Foo lhs, Foo rhs) // non-member variant 
{ // declared outside the class 
    // could be just a call to the member variant 
    lhs.operator+(rhs); 
    // I usually do this when implementing std::stream operators, 
    // don't remember why just now. 
} 

非成員不需要添加爲朋友,也可以是,如果它需要訪問內部狀態。 如果我沒有記錯的話,非成員在編譯器上的模板化代碼和名稱空間方面有一些優勢,在非成員變體中的朋友也可以很好地記錄在類之外有一個函數,具體到這個類。它告訴我,如果我改變這個班,我可能不得不查看非成員操作員,以確保我沒有破壞任何東西。

0

大多數操作員應該定義爲成員。

class MyClass 
{ 
... 
public: 
    const MyClass& operator+=(const MyClass&); 
}; 

位,這是在行爲以下相同:

class MyClass {...}; 
const MyClass& operator+=(const MyClass&, const MyClass&); 

的在第一示例中隱含this很是類似的第一個參數的第二示例。如果第二個示例需要訪問MyClass的內部狀態,則需要使用friend ed。

class MyClass 
{ 
    friend const MyClass& operator+=(const MyClass&, const MyClass&); 
}; 
const MyClass& operator+=(const MyClass&, const MyClass&); 

原型的例外是operator<<std::ostream

std::ostream& operator<<(std::ostream&, const MyClass&); 

這在邏輯上是MyClass的一員,但由於參數的順序它必須是兩個類的非會員或std::ostream成員。由於您無法將成員添加到std::ostream,因此必須將其定義爲非成員。

+0

'operator +'通常會返回一個新的類型實例,即'T operator +(const T&lhs,const T & rhs);'。如果返回一個引用,它應該引用什麼?另外,'operator +通常以非成員的方式實現,以允許左操作數的隱式轉換(如果將操作符實現爲成員,則這將不被允許)。 –

0

一個小例子:(我沒試過編譯這個代碼,但我希望它的工作原理)

class MyClass 
{ 
public: 
    MyClass operator+(const MyClass& other) const; //member operator declaration 

    friend MyClass operator-(const MyClass& first, const MyClass& second); //non-member operator friend declaration 
private: 
    int _a; 
} 

//member operator definition 
MyClass MyClass::operator+(const MyClass& other) const 
{ 
    MyClass result; 
    result._a = _a + other._a; 
    return result; 
} 

//non-member operator definition 
MyClass MyClass::operator-(const MyClass& first, const MyClass& second) 
{ 
    MyClass result; 
    result._a = first._a - second._a; 
    return result; 
} 

心靈的差異:在成員運營商定義,我不第一_a前後指定什麼「=」 - 假設這個 - > _ a。

只有當您的類的實例是操作符的第一個參數時,纔可以使用成員操作符函數。例如,如果您想要執行類似2 + myClassObject的操作,則需要覆蓋非成員操作員MyClass MyClass::operator+(int first, const MyClass& second)(或者您想要的任何返回值)。

還請注意,我只需要我的非會員運營商的友誼聲明有權訪問私人_a字段。