C++运算符重载 - 为什么友元函数更受青睐?

5

接着上一个问题,我想问为什么在C++操作符重载中更倾向于使用“友元”形式的加法。

总结一下:

对于加法操作符重载,有两种方法:

int operator+(Object& e);
friend int operator+(Object& left, Object& right);

为什么第二个(好友)表单更受青睐?有哪些优点?

1
最好引用上一个问题中相关的部分,这样人们就不必点击它(以防该问题消失)。 - nneonneo
2个回答

5
非成员版本(包括朋友或其他)是首选,因为它可以在运算符的左侧和右侧都支持隐式转换。
假设有一个类型隐式地可以转换为Object:
struct Widget
{
  operator Object() const;
};

仅当Widget的实例出现在左侧时,才能调用非成员版本:

Widget w;
Object o;

o + w; // can call Object::operator+( Object & ) since left-hand side is Object
w + o; // can only call operator+( Object &, Object & )

针对您的评论:

通过在 Widget 中定义转换运算符,我们通知编译器可以自动将 Widget 实例转换为 Object 实例。

Widget w;
Object o = w;  // conversion

在表达式o + w中,编译器使用将w转换为Object所生成的参数,调用Object::operator+( Object & )。因此,结果与写o + w.operator Object()相同。
但是,在表达式w + o中,编译器会查找不存在的Widget::operator+或者非成员operator+( Widget, Object )。后者可以通过像上面那样将w转换为Object来调用。

我不太理解小部件/对象结构代码,你能否提供一个简单而极短的例子? - Johnny Pauling

2
规则并不是普遍适用的:当您实现一个逻辑对称的操作,该操作接受相同类型的两个参数时,例如您所示范的情况,应优先使用“friend”版本。
此实现强调了该操作确实是对称的:它不是“对象this”将“Object e”添加到自身,而是将“lhs”和“rhs”相加。
在操作是非对称的情况下,例如将“int”添加到迭代器时,应优先使用第一种实现运算符的方式。
Object& operator+(int& offset);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接