【问题标题】:Overload operators as member function or non-member (friend) function?将运算符重载为成员函数或非成员(朋友)函数?
【发布时间】:2010-12-26 16:49:07
【问题描述】:

我目前正在创建一个实用程序类,其中包含重载运算符。将它们设为成员或非成员 (friend) 函数的优缺点是什么?还是根本不重要?也许有一个最佳实践?

【问题讨论】:

    标签: c++ function operator-overloading friend


    【解决方案1】:

    没有什么能比得上最佳实践,但这取决于您要重载的运算符..

    例如。

    1. >> 不能作为成员函数重载。

    2. 假设你想做这样的事情:obj1 = 2 * obj2 然后选择非成员函数

    对于二元运算符重载,成员函数只需要1个参数(调用对象是隐式传递的),而非成员函数需要2个参数。

    【讨论】:

    • cout 和 cin 是 iostream 中类的实例,它们不能重载,OP 说的是重载运算符。
    • <<>> 当然可以作为成员函数重载,但如果您想将它们用作流提取/插入运算符则不能。如果您想像丹尼斯·里奇(Dennis Ritchie)那样将它们用作轮班操作员,没问题。
    【解决方案2】:

    每个运营商都有自己的考虑。例如,

    至于通过继承允许特化,一个常见的模式是通过一个虚成员函数来实现一个非成员操作符(例如操作符

    【讨论】:

    • 现在这已经揭示了困扰我的恶性循环“太多/太少的运营商”。谢谢!另外,作为一个初学者程序员,我会说与双方自动类型转换相关的观察是一个非常好的观察,并且可能在将来有用。
    【解决方案3】:

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

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

    【讨论】:

    • 返回const A 有什么意义?我已经看过几次(返回一个 const 值),但从未找到任何实际原因......
    • @Matthieu M.,它阻止我们编写“(a+b)=c”,这对于 int 等原始类型本来就不可能。
    • @Jagannath,您忘记了两个参数声明的“const”。
    【解决方案4】:

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

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

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

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

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

    【讨论】:

      【解决方案5】:

      如果您计划实现流式操作符(>),那么它们将是非成员方法,因为您的对象位于操作符的左侧。

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

      对于其他(比较和数学),您应该查看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+= 有效地实现,因此您只需编写一次代码。

      【讨论】:

        【解决方案6】:

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

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

        另一个原因:更少的耦合。非成员函数的耦合度不如成员函数。这几乎总是一件好事。

        【讨论】: