重载操作符作为成员函数还是非成员(朋友)函数?

时间:2009-12-15 06:00:45

标签: c++ function operator-overloading friend

我目前正在创建一个将在其中重载运算符的实用程序类。使它们成为成员或非成员(friend)职能的利弊是什么?或者它是否重要?也许这是最好的做法?

6 个答案:

答案 0 :(得分:20)

我将使用“C ++编码标准:101规则,指南和最佳实践”:如果您可以将其作为非成员函数执行,则将其作为非成员函数(在同一名称空间中)执行。

其中一个原因:隐式类型转换效果更好。示例:您有一个带有重载运算符*的复杂类。如果要编写2.0 * aComplexNumber,则需要运算符*为非成员函数。

另一个原因:耦合较少。非成员函数与成员函数的耦合程度较低。这几乎总是一件好事。

答案 1 :(得分:16)

每个运营商都有自己的考虑因素。例如,<< operator(当用于流输出,而不是位移)时会将ostream作为其第一个参数,因此它不能成为您的类的成员。如果您正在实施加法运算符,您可能希望从双方的自动类型转换中受益,因此您也将使用非成员等等...

至于允许通过继承进行特化,一个常见的模式是根据虚拟成员函数实现非成员运算符(例如,运算符<<<对正在传递的对象调用虚函数print())。

答案 2 :(得分:4)

如果您计划实施流媒体运营商(<<>>),那么它们将是非会员方法,因为您的对象位于运营商的左侧。

如果您计划实施 - >,>()或[],它们自然是成员方法。

对于其他人(比较和数学),您应该查看Boost.Operators,这确实有帮助。

例如,如果要实现以下运算符:

MyClass& MyClass::operator+=(int);
MyClass operator+(const MyClass&, int);
MyClass operator+(int, const MyClass&);

你只需写:

class MyClass: boost::operator::addable<MyClass,int> // no need for public there
{
public:
  MyClass& operator+=(int);
private:
};

2 operator+将自动生成为非会员,可让您从自动转化中受益。它们将在operator+=期间有效实施,因此您只需编写一次代码。

答案 3 :(得分:3)

如果你正在实现op,那么很可能你需要实现op =。即如果你正在重载+运算符,那么你应该实现+ =。 如果您正在进行后增量或重载+运算符,请确保将const返回到对象。 因此,如果重载operator +,则将其实现为非成员运算符,并在其中使用+ =运算符。例如。

const A operator+(const A& lhs, const A& rhs)
{
   A ret(lhs);
   ret += rhs;
   return ret;
}

答案 4 :(得分:2)

对于二元运算符,成员函数的一个限制是左对象必须是您的类类型。这可以限制使用操作员对称。

考虑一个简单的字符串类:

class str
{
public:
    str(const char *);
    str(const str &other);
};

如果将operator +作为成员函数实现,而str("1") + "2"将编译,"1" + str("2")将无法编译。

但是如果你将operator +作为非成员函数实现,那么这两个语句都是合法的。

答案 5 :(得分:0)

没有什么比最佳做法更好,但这取决于您正在超载的运营商..

例如

  1. &gt;&gt; &lt;&lt; 不能作为成员函数重载。

  2. 假设你想这样做: obj1 = 2 * obj2 然后选择非会员功能

  3. 对于二元运算符重载成员函数只需要1个参数(调用对象被非常传递),而非成员函数则需要2个参数。