我读到声明为成员函数的重载运算符是不对称的,因为它只能有一个参数,而自动传递的另一个参数是this
指针。所以没有标准来比较它们。另一方面,声明为 a 的重载运算符friend
是对称的,因为我们传递了两个相同类型的参数,因此可以比较它们。
我的问题是,当我仍然可以将指针的左值与引用进行比较时,为什么首选朋友?(使用非对称版本的结果与对称版本相同) 为什么 STL 算法只使用对称版本?
我读到声明为成员函数的重载运算符是不对称的,因为它只能有一个参数,而自动传递的另一个参数是this
指针。所以没有标准来比较它们。另一方面,声明为 a 的重载运算符friend
是对称的,因为我们传递了两个相同类型的参数,因此可以比较它们。
我的问题是,当我仍然可以将指针的左值与引用进行比较时,为什么首选朋友?(使用非对称版本的结果与对称版本相同) 为什么 STL 算法只使用对称版本?
如果将运算符重载函数定义为成员函数,则编译器会将表达式s1 + s2
转换为s1.operator+(s2)
. 这意味着,运算符重载的成员函数在第一个操作数上被调用。这就是成员函数的工作原理!
但是如果第一个操作数不是一个类怎么办?如果我们想要重载第一个操作数不是类类型的运算符,而不是说double
. 所以你不能这样写 10.0 + s2
。但是,您可以为表达式编写运算符重载成员函数,例如s1 + 10.0
.
为了解决这个排序问题,我们将运算符重载函数定义为friend
IF 它需要访问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
}
阅读这些:
操作数排序的小问题
非成员函数如何改进封装
运算符重载和成员函数运算符重载之间不一定有区别,friend
因为它是全局运算符重载和成员函数运算符重载之间的区别。
首选全局运算符重载的一个原因是,如果您希望允许类类型出现在二元运算符右侧的表达式。例如:
Foo f = 100;
int x = 10;
cout << x + f;
这仅在存在全局运算符重载时才有效
Foo 运算符 + (int x, const Foo& f);
请注意,全局运算符重载不一定是friend
函数。仅当它需要访问 的私有成员时才需要这样做Foo
,但情况并非总是如此。
无论如何,如果Foo
只有成员函数运算符重载,例如:
class Foo
{
...
Foo operator + (int x);
...
};
...那么我们将只能有一个Foo
实例出现在加号运算符左侧的表达式。