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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4622330/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 15:57:44  来源:igfitidea点击:

Operator overloading : member function vs. non-member function?

c++operator-overloadingmember-functionsfriend-functionnon-member-functions

提问by badmaash

I read that an overloaded operator declared as member function is asymmetricbecause it can have only one parameter and the other parameter passed automatically is the thispointer. So no standard exists to compare them. On the other hand, overloaded operator declared as a friendis symmetricbecause we pass two arguments of the same type and hence, they can be compared.

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

My question is that when i can still compare a pointer's lvalue to a reference, why are friends preferred? (using an asymmetric version gives the same results as symmetric) Why do STL algorithms use only symmetric versions?

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

回答by Nawaz

If you define your operator overloaded function as member function, then the compiler translates expressions like s1 + s2into s1.operator+(s2). That means, the operator overloaded member function gets invoked on the first operand.That is how member functions work!

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

But what if the first operand is not a class? There's a major problem if we want to overload an operator where the first operand is not a class type, rather say double.So you cannot write like this 10.0 + s2. However, you can write operator overloaded member function for expressions like s1 + 10.0.

但是如果第一个操作数不是一个类呢?如果我们想重载第一个操作数不是类类型的运算符,则有一个主要问题,比如double所以你不能这样写 10.0 + s2。但是,您可以为像s1 + 10.0.

To solve this orderingproblem, we define operator overloaded function as friendIF it needs to access privatemembers. Make it friendONLY when it needs to access private members.Otherwise simply make it non-friend non-memberfunction to improveencapsulation!

为了解决这个排序问题,我们将运算符重载函数定义为friendIF 它需要访问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
}

Read these :
A slight problem of ordering in operands
How Non-Member Functions Improve Encapsulation

阅读这些:
操作数排序的一个小问题
非成员函数如何改进封装

回答by Charles Salvia

It's not necessarily a distinction between friendoperator overloads and member function operator overloads as it is between globaloperator overloads and member function operator overloads.

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

One reason to prefer a globaloperator overload is if you want to allow expressions where the class type appears on the righthand side of a binary operator. For example:

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

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

This only works if there is a global operator overload for

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

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

Foo 运算符 + (int x, const Foo& f);

Note that the global operator overload doesn't necessarily need to be a friendfunction. This is only necessary if it needs access to private members of Foo, but that is not always the case.

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

Regardless, if Fooonly had a member function operator overload, like:

无论如何,如果Foo只有一个成员函数运算符重载,例如:

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

...then we would only be able to have expressions where a Fooinstance appears on the leftof the plus operator.

...那么我们只能有一个Foo实例出现在加号运算符左侧的表达式。