运算符重载(朋友和成员函数)

时间:2010-05-05 05:07:38

标签: c++ oop operator-overloading

使用friend关键字的运算符重载和作为类中的成员函数有什么区别?

此外,任何一元运算符重载(即作为朋友与成员函数)的情况有何不同?

5 个答案:

答案 0 :(得分:12)

Jacob是正确的......在类中声明的friend函数可以访问该类,但它根本不在类中,其他人都可以访问它。

对于不是类成员的运算符重载(也称为自由函数,它可能是朋友,或者可能不是),参数与操作数相同。对于作为类成员的一个,第一个操作数是“隐含参数”,它变为this

隐式参数在几个方面与自由函数的第一个参数不同:

  • 它的类型是引用类,而free函数可以为它的第一个参数声明任何类型。
  • 它不参与隐式类型转换。 (它不会被转换构造函数初始化。)
  • 它确实参与虚拟覆盖分辨率。 (virtual重载将由第一个操作数的动态类型选择,这对于没有额外代码的自由函数是不可能的。)

一元,二元或一元的情况是相同的(在operator()的情况下)。

成员突变特权:更改第一个操作数的运算符(例如+==,前缀++)应该实现为成员函数,并且应该专门实现所有重载的内容。 Postfix ++是二等公民;它实现为Obj ret = *this; ++ this; return ret;。请注意,这有时会扩展到copy-constructors,它可能包含*this = initializer

通勤者的自由规则:只有交换运营商(例如/)应该是自由职能;所有其他运营商(例如一元一事)应该是成员。交换运算符固有地制作对象的副本;它们被实现为Obj ret = lhs; ret @= rhs; return ret;,其中@是可交换运算符,lhsrhs分别是左侧和右侧参数。

C ++友谊的黄金法则:避免友谊。 friend污染了设计的语义。 重载推论:如果您遵循上述规则,重载很简单,那么friend是无害的。 friend样板过载定义允许将它们放在class {括号内。

请注意,某些运算符不能是自由函数:=->[](),因为标准在第13.5节中明确说明了这一点。我认为这就是全部...我认为一元&*也是如此,但我显然是错的。但是,总是作为成员超载,并且只有经过深思熟虑后才会过载!

答案 1 :(得分:3)

不同之处在于,friended函数实际上处于全局范围内,因此您无需成为该类的实例即可访问它。

答案 2 :(得分:1)

成员函数要求左手操作符必须属于该类型。 友元函数可以允许左手操作符隐式转换。

例如,假设我们创建了一个BigInt类。我们创建了一个成员函数operator +来获取BigInt的右手操作符。

现在让我们也说BigInt有一个带有常规int的构造函数。此构造函数不是显式的(显式关键字),它需要一个参数。这意味着C ++可以从int转换为BigInt。

当我们有这些东西时,我们可以这样做:

BigInt foo(5); BigInt酒吧; bar = foo + 5;

但我们不能这样做:

BigInt foo(5) BigInt酒吧; bar = 5 + foo;

但是,如果我们使用友元函数而不是成员函数,那么两者都可以工作。

答案 3 :(得分:1)

成员函数要求左手操作符必须属于该类型。友元函数可以允许左手操作符隐式转换。

答案 4 :(得分:0)

可以在rvalues上调用成员函数,而不能使用rvalues调用接受对非const的引用的自由函数。例如,++function_returning_iterator_by_value()仅在您将operator++作为成员实施时进行编译。