C++运算符覆盖 - 为什么首选朋友

C++ operator override - why is it friend preferred?

本文关键字:朋友 为什么 运算符 覆盖 C++      更新时间:2023-10-16

继续上一个问题,我想问为什么首选C++运算符覆盖中的"朋友"加法形式

总结一下:

对于加法运算符覆盖,有两种方法可以做到这一点:

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

为什么首选第二种(朋友)形式?有哪些优势?

非成员版本(友元或其他版本)是首选版本,因为它可以支持运算符左侧和右侧的隐式转换。

给定一个可隐式转换为 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来调用。

该规则不是通用的:当您实现采用两个相同类型的参数的逻辑对称操作时,首选friend版本,例如您的帖子演示的情况。

此实现强调了操作真正对称的事实:它不是向自身添加Object e的"对象这个"——而是lhsrhs的添加。

在操作非对称的情况下 - 例如,当您向迭代器添加int时,您应该首选实现运算符的第一种方法,即

Object& operator+(int& offset);