运算符重载:成员函数与非成员函数?
我读过一个被声明为成员函数的重载运算符是不对称的,因为它只能有一个参数,而另一个自动传递的参数是'this'指针。 所以没有标准来比较它们。 另一方面,声明为朋友的重载运算符是对称的,因为我们传递了两个相同类型的参数,因此可以进行比较。 我的问题是,当我仍然可以比较指针的左值参考,为什么朋友首选? (使用不对称版本会得到与对称相同的结果)为什么STL算法只使用对称版本?
如果将运算符重载函数定义为成员函数,则编译器将诸如s1 + s2
表达式转换为s1.operator+(s2)
。 这意味着,操作符重载成员函数被调用的第一个操作数。 这就是成员函数的工作方式!
但是如果第一个操作数不是一个类呢? 如果我们想要在第一个操作数不是类类型的情况下重载一个操作符,那么存在一个主要的问题,而不是类型。 所以你不能像这样写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 }
阅读这些:
在操作数中排序的一个小问题
非成员函数如何改进封装
它不一定是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
实例出现在加号运算符的左边 。