全局运算符和成员运算符的区别
定义一个接受类的两个引用的全局运算符和定义一个仅接受正确操作数的成员运算符之间有区别吗?
全球:
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;
};
}
Is there a difference between defining a global operator that takes two references for a class and defining a member operator that takes only the right operand?
Global:
class X
{
public:
int value;
};
bool operator==(X& left, X& right)
{
return left.value == right.value;
};
Member:
class X
{
int value;
bool operator==( X& right)
{
return value == right.value;
};
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
使用非成员运算符(通常声明为友元)的原因之一是因为左侧是执行操作的一侧。
Obj::operator+
对于: 很好,但是对于:
它不起作用。 为此,您需要类似的东西:
One reason to use non-member operators (typically declared as friends) is because the left-hand side is the one that does the operation.
Obj::operator+
is fine for:but for:
it won't work. For this, you need something like:
您最明智的选择是将其设为好友功能。
正如 JaredPar 提到的,全局实现无法访问受保护的和私有的类成员,但成员函数也存在问题。
C++ 允许函数参数的隐式转换,但不允许
this
的隐式转换。如果存在可以转换为 X 类的类型:
只有以下某些表达式将使用成员函数进行编译。
为了两全其美,解决方案是以朋友的身份实现:
Your smartest option is to make it a friend function.
As JaredPar mentions, the global implementation cannot access protected and private class members, but there's a problem with the member function too.
C++ will allow implicit conversions of function parameters, but not an implicit conversion of
this
.If types exist that can be converted to your X class:
Only some of the following expressions will compile with a member function.
The solution, to get the best of both worlds, is to implement this as a friend:
总结一下 Codebender 的答案:
成员运算符不是对称的。 编译器无法使用左侧和右侧运算符执行相同数量的操作。
在上面的代码中,如果运算符是成员函数,则将无法编译,而如果运算符是自由函数,则它将按预期工作。
一般来说,常见的模式是将必须是成员函数的运算符实现为成员,其余的作为委托成员运算符的自由函数:
To sum up to the answer by Codebender:
Member operators are not symmetric. The compiler cannot perform the same number of operations with the left and right hand side operators.
In the code above will fail to compile if the operator is a member function while it will work as expected if the operator is a free function.
In general a common pattern is implementing the operators that must be member functions as members and the rest as free functions that delegate on the member operators:
至少有一处不同。 成员运算符受访问修饰符的约束,可以是公共的、受保护的或私有的。 全局成员变量不受访问修饰符限制。
当您想要禁用某些运算符(例如赋值)时,这特别有用。
您可以通过仅声明全局运算符来达到相同的效果。 但它会导致链接错误与编译错误(nipick:是的,它会导致 Foo 内的链接错误)
There is at least one difference. A member operator is subject to access modifiers and can be public, protected or private. A global member variable is not subject to access modifier restrictions.
This is particularly helpful when you want to disable certain operators like assignment
You could achieve the same effect by having a declared only global operator. But it would result in a link error vs. a compile error (nipick: yes it would result in a link error within Foo)
这是一个真实的例子,其中差异并不明显:
这是因为第一种形式使用基类中的相等运算符,它可以将其右侧转换为
Base
。 但派生类相等运算符不能执行相反的操作,因此会出现错误。如果将基类的运算符声明为全局函数,则两个示例都可以工作(派生类中没有相等运算符也可以解决问题,但有时需要它)。
Here's a real example where the difference isn't obvious:
This is because the first form uses equality operator from base class, which can convert its right hand side to
Base
. But the derived class equality operator can't do the opposite, hence the error.If the operator for the base class was declared as a global function instead, both examples would work (not having an equality operator in derived class would also fix the issue, but sometimes it is needed).