我读到过,将重载运算符声明为成员函数是不对称的,因为它只能有一个参数,而自动传递的其他参数是this
指针。因此,不存在标准来比较它们。另一方面,作为friend
声明的重载运算符是对称的,因为我们传递了两个相同类型的参数,因此它们可以进行比较。
我的问题是,当我仍然可以将指针的lvalue与引用进行比较时,为什么要使用friend?(使用不对称版本会产生与对称版本相同的结果)为什么STL算法仅使用对称版本?
我读到过,将重载运算符声明为成员函数是不对称的,因为它只能有一个参数,而自动传递的其他参数是this
指针。因此,不存在标准来比较它们。另一方面,作为friend
声明的重载运算符是对称的,因为我们传递了两个相同类型的参数,因此它们可以进行比较。
我的问题是,当我仍然可以将指针的lvalue与引用进行比较时,为什么要使用friend?(使用不对称版本会产生与对称版本相同的结果)为什么STL算法仅使用对称版本?
s1 + s2
这样的表达式转换为 s1.operator+(s2)
。这意味着运算符重载成员函数被调用时第一个操作数被传递给它。这就是成员函数的工作方式!double
)作为第一个操作数的运算符,那就有一个大问题了。所以你不能这样写:10.0 + s2
。不过,你可以对像 s1 + 10.0
这样的表达式编写运算符重载成员函数。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/b
。 - edA-qa mort-ora-yfriend
,常见的方法是利用操作赋值运算符来实现它们(这些运算符几乎肯定是公开成员)。例如,你可以将 T T::operator+=(const T &rhs)
定义为成员函数,然后将非成员函数 T operator(T lhs, const T &rhs)
定义为 return lhs += rhs;
。非成员函数应该在与类相同的命名空间中定义。 - Adrian McCarthy这并不一定是朋友函数重载和成员函数重载之间的区别,而是全局运算符重载和成员函数运算符重载之间的区别。
选择使用全局运算符重载的一个原因是,如果您想允许表达式中类类型出现在二元运算符的右侧,则可以这样做。例如:
Foo f = 100;
int x = 10;
cout << x + f;
只有存在全局运算符重载,如下代码:
请注意,全局运算符重载不一定需要是Foo operator + (int x, const Foo& f);
friend
函数。只有在需要访问Foo
的私有成员变量时才需要这样,但并不总是这种情况。Foo
只有一个类成员函数的运算符重载,例如:class Foo
{
...
Foo operator + (int x);
...
};
如果我们这样做, 那么我们只能有这样的表达式,Foo
实例只能出现在加号操作符的左侧。
operator[]
也可以作为一个带有多个参数的成员函数进行重载。 - Frankyoperator[]
也可以作为一个带有多个参数的成员函数进行重载。 - undefined