运算符重载:成员函数与非成员函数?

时间:2011-01-07 03:43:15

标签: c++ operator-overloading member-functions friend-function non-member-functions

我读到一个声明为成员函数的重载运算符是非对称,因为它只能有一个参数而另一个自动传递的参数是this指针。所以没有比较它们的标准。另一方面,声明为friend的重载运算符是对称因为我们传递了两个相同类型的参数,因此可以对它们进行比较。

我的问题是,当我仍然可以将指针的左值与参考值进行比较时,为什么会选择朋友? (使用非对称版本提供与对称相同的结果) 为什么STL算法只使用对称版本?

2 个答案:

答案 0 :(得分:129)

如果将运算符重载函数定义为成员函数,则编译器会将s1 + s2之类的表达式转换为s1.operator+(s2)这意味着,在第一个操作数上调用运算符重载的成员函数。这就是成员函数的工作方式!

但是如果第一个操作数不是一个类呢? 如果我们想要重载第一个操作数不是类类型的运算符,而不是double,则会出现一个主要问题。所以你不能像这样写10.0 + s2。但是,您可以为s1 + 10.0等表达式编写运算符重载成员函数。

要解决此排序问题,我们将运算符重载函数定义为friend如果它需要访问private成员。 仅在需要访问私人会员时才friend 。否则只需将非朋友非会员功能设为改进封装!

class Sample
{
 public:
    Sample operator + (const Sample& op2); //works with s1 + s2
    Sample operator + (double op2); //works with s1 + 10.0

   //Make it `friend` only when it needs to access private members. 
   //Otherwise simply make it **non-friend non-member** function.
    friend Sample operator + (double op1, const Sample& op2); //works with 10.0 + s2
}

阅读这些:
A slight problem of ordering in operands
How Non-Member Functions Improve Encapsulation

答案 1 :(得分:17)

它不一定区分friend运算符重载和成员函数运算符重载,因为它位于全局运算符重载和成员函数运算符重载之间。

首选全局运算符重载的一个原因是,如果要允许类型出现在二元运算符的 right 手侧的表达式。例如:

Foo f = 100;
int x = 10;
cout << x + f;

仅当

存在全局运算符重载时才有效
  

Foo operator +(int x,const Foo&amp; f);

请注意,全局运算符重载不一定需要是friend函数。只有在需要访问Foo的私有成员时才需要这样做,但情况并非总是如此。

无论如何,如果Foo只有成员函数操作符重载,例如:

class Foo
{
  ...
  Foo operator + (int x);
  ...
};

...然后我们只能在plus运算符的 left 上出现Foo实例的表达式。