重载+ =或 - =运算符的好处

时间:2012-10-05 11:52:53

标签: c++ oop templates operator-overloading complex-numbers

最近,我完成了一项任务,即使用模板重载复杂类的基本功能主义者(+, - ,共轭...)。我不得不出汗一点,找出适当的返回类型,(铸造到更高的类型),但最后,我得到它完美的工作。 这就是我班级的样子 -

template <typename T> class complex_t
{ 
private:
    T real;
    T imaginary;

public:

complex_t(T X, T Y)
  {
    real=X;
    imaginary=Y;
  }
}

但我没有得到满分,因为我没有实现+ =, - =等运算符。 为什么实施这些运营商很重要?这样做真的能带来什么特别的好处吗? 任何人都可以分享一些想法吗?

提前致谢,

7 个答案:

答案 0 :(得分:9)

重载运算符 - 允许类“Foo”的用户编写如下代码:

Foo f1 = ...;
Foo f2 = ...;
f2 = f2 - f1;

重载运算符 - =允许用户编写

Foo f1 = ...;
Foo f2 = ...;

f2 -= f1;

除非你重载 - =,否则第二个例子将无效,你的用户可能希望这样做。

编辑以纳入效率点(我的答案正在上升,所以我想我会从其他答案中总结出一个反复出现的观点,将所有细节保留在一个位置。感谢larsmans和Benjamin)

f2 -= f1通常比f2 = f2 - f1效率更高,原因有两个:

  • operator -需要获取this的副本,然后才能修改副本并将其返回。
  • operator -还需要按值返回结果(它不能返回对堆栈对象的引用),可能导致第二个副本。
另一方面,

operator -=会修改this,因此不会复制。

答案 1 :(得分:9)

如果您有两个对象A和B,并且想要在没有operator+=的情况下将A增加A,则可以执行以下操作:

A = A + B;

在正常的实现中,这将涉及创建第三个(临时)对象,然后将其复制回A.但是,使用operator+=,A可以在适当的位置进行修改,因此通常较少工作,因此更有效率。

也许更重要的是,这是语言的惯用语。 C ++程序员希望如果他们能做到这一点:

A = A + B;

他们也可以这样做:

A += B;

答案 2 :(得分:6)

+=和朋友就地工作,因此您不必返回班级的新实例。对于复杂的数字,这可能不是什么大问题,但是对于更大的结构,复制可能很昂贵。

作为一个例子,假设你在数学意义上实现了支持任意长度的向量。

class Vector
{
    std::vector<double> elements;

  public:
    Vector operator+(double x)
    {
        // must return a copy!
        Vector v(*this);
        for (size_t i=0; i < elements.size(); i++)
            v.elements[i] += x;
        return v;
    }

    Vector &operator+=(double x)
    {
        // in-place operation
        for (size_t i=0; i < elements.size(); i++)
            elements[i] += x;
        return *this;
    }
};

答案 3 :(得分:5)

首先,如果你给我一个带+运算符的类,我希望+ =也可以运行。 但是,这不是自动生成的,因此您需要实现它。

其次,正如其他人之前指出的那样,根据你的类的实现和总和操作的定义,你可能能够实现+ =更高效,而不仅仅是以明显的方式重新使用你的+运算符(这是编译器可以自动生成的方式,但不是。)

答案 4 :(得分:4)

因为这是内置运营商的工作方式。任何时候你有 一个二元运算符op,你有一个变体 op=a op= b;就是a = a op b; 相当于a,但+仅为+= 评估一次。如果您要定义重载运算符,则应该 模仿他们在内置运算符上的行为(以及行为 不能在内置运算符上自然形成图案,你不应该这样 超载)。提供<但未提供<=的情况与此类似 提供op=,但不提供op

实际上,实现算术运算符的常用方法是 仅定义类中的op=运算符,然后 从定义类的模板的实例化派生 使用class MyType : public BinaryOperators<MyType> { public: MyType& operator+=( MyType const& other ); // ... }; 的{​​{1}}运营商 运营商,如:

BinaryOperators

其中template <typename ValueType> class BinaryOperators { friend ValueType operator+( ValueType const& lhs, ValueType const& rhs ) { ValueType results( lhs ); results += rhs; return results; } // ... }; 类似于:

friend

(在这种情况下,{{1}}声明只是一个允许的技巧 自由函数在类中完全定义。)

答案 5 :(得分:3)

+运算符将通过设计分配和构造一个全新的对象,而+ =运算符可以修改现有的对象。这使得您可以比用户用val1 = val1 + val2替换它时更有效地实现+ =运算符。

另外,当我知道一个类重载+时,我也希望它超载+ =。

答案 6 :(得分:1)

除了其他程序员希望覆盖+ =的可能性之外,我认为它可能是继承和覆盖功能所必需的。在一个非常抽象且可能不正确的意义上,想象一下我们想要在包含我们特殊整数的整数列表上执行操作:

MyModifiedInteger extends Integer {
  private boolean bigNumberFlag = false;
  ...
  @Override
  public void +=(int i) {
    this = this + i;
    if (this > 100) {
      this.bigNumberFlag = true;
    }
  }
}
MyModifiedInteger myModifiedInt = new MyModifiedInteger();
List<Integer> integers = new ArrayList<Integer>();
integers.add(myModifiedInt);
for (Integer i : integers) {
  i+=5;
}

这里的想法(如果我正确地应用了我的java继承)是在我的整数上使用+ =运算符以及可能以不同方式处理+ =运算的继承类。