2009-07-17 133 views
30

定義一個全局運算符(它接受一個類的兩個引用並定義一個僅接受正確操作數的成員運算符)有區別嗎?全球運營商和會員運營商之間的區別

全球:

class X 
{ 
public: 
    int value; 
}; 

bool operator==(X& left, X& right) 
{ 
    return left.value == right.value; 
}; 

會員:

class X 
{ 
    int value; 
    bool operator==(X& right) 
    { 
     return value == right.value; 
    }; 
} 
+2

優良作法申報參數不僅參考,但也是const,只要你確定你可以。比較運算符可以是const並且肯定可以採用const引用。 (如果沒有別的,這是承諾編譯器,它允許它做更多的優化。) – 2016-03-16 21:08:16

回答

39

使用非成員操作符(通常聲明爲朋友)的一個原因是,手邊是做手術的一方。 Obj::operator+是罰款:

obj + 2 

但:

2 + obj 

將無法​​正常工作。對於這一點,你需要的東西,如:

class Obj 
{ 
    friend Obj operator+(const Obj& lhs, int i); 
    friend Obj operator+(int i, const Obj& rhs); 
}; 

Obj operator+(const Obj& lhs, int i) { ... } 
Obj operator+(int i, const Obj& rhs) { ... } 
5

至少有一個區別。會員運營商需要訪問修改器,並且可以是公共的,受保護的或私有的。全局成員變量不受訪問修飾符限制。

,當你想通過具有唯一宣佈全球運營商禁用某些運營商如分配

class Foo { 
    ... 
private: 
    Foo& operator=(const Foo&); 
}; 

你可以達到同樣的效果,這是特別有幫助。但它會導致鏈接錯誤與編譯錯誤(nipick:是它會導致Foo內的鏈接錯誤)

+0

一個聲明的唯一的全球運營商將不會鏈接(即沒有節目),而私人會員運營商將。只有私有成員的非法使用纔會導致編譯錯誤。正確? – 2012-07-14 10:11:10

6

你最明智的選擇是使它成爲一個友元函數

正如JaredPar提到的,全局實現無法訪問受保護的私有類成員,但成員函數也存在問題。

C++將允許函數參數的隱式轉換,但不允許隱式轉換this

如果存在的類型,可以被轉換成你的X類:

class Y 
{ 
public: 
    operator X(); // Y objects may be converted to X 
}; 


X x1, x2; 
Y y1, y2; 

只有一些下列表達式將與成員函數編譯。

x1 == x2; // Compiles with both implementations 
x1 == y1; // Compiles with both implementations 
y1 == x1; // ERROR! Member function can't convert this to type X 
y1 == y2; // ERROR! Member function can't convert this to type X 

的解決方案,以獲得兩全其美的,是實現這是一個朋友:

class X 
{ 
    int value; 

public: 

    friend bool operator==(X& left, X& right) 
    { 
     return left.value == right.value; 
    }; 
}; 
+1

這不是一個錯誤,這是一個功能;)我討厭隱式轉換... – 2013-02-21 03:47:37

6

要通過Codebender總結答案:

會員運營商不對稱的。編譯器無法使用左側和右側運算符執行相同數量的操作。

struct Example 
{ 
    Example(int value = 0) : value(value) {} 
    int value; 

    Example operator+(Example const & rhs); // option 1 
}; 
Example operator+(Example const & lhs, Example const & rhs); // option 2 
int main() 
{ 
    Example a(10); 
    Example b = 10 + a; 
} 

在上面的代碼將無法被編譯,如果操作員是一個成員函數而如預期如果操作者是一個免費的功能,將工作。

一般的通用模式正在執行所必須的成員函數操作者作爲成員,其餘爲自由函數的構件運算符代表:

class X 
{ 
public: 
    X& operator+=(X const & rhs); 
}; 
X operator+(X lhs, X const & rhs) 
{ 
    lhs += rhs; // lhs was passed by value so it is a copy 
    return lhs; 
}