2009-07-17 90 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; 
}