4

Is it right to define operator += in this way ?!

void operator +=(const BigNumber& other)
{
    *this=(*this) + other;
}

In a class like this :

class BigNumber
{
public:
   //....
    BigNumber operator +(const BigNumber& other)
    {
        return sum(other);
    }

  //....
}
uchar
  • 2,552
  • 4
  • 29
  • 50
  • 1
    See [this duplicate](http://stackoverflow.com/questions/4421706/operator-overloading) for a definitive guide to all aspects of operator overloading, including the question you asked. Specifically, see [this answer](http://stackoverflow.com/a/4421719/1227469) and scroll down to "binary arithmetic operators" – JBentley Jan 18 '14 at 14:12

2 Answers2

6

Yes. But the right way is to implement operator+ in terms of operator+=:

struct foo
{
    int value;

    foo& operator+=( const foo& other )
    {
        value += foo.value;
        return *this ;
    }

    friend foo operator+( foo lhs , const foo& rhs )
    {
        return lhs += rhs;
    }
};

Why?

First of all, the binary operator+() shouldn't be defined as member function instead of free function. This allows you to implement addition where the first parameter is not a foo. The common idiom is to declare it friend inside the class to ride over encapsulation.

Second, this way provides a coherent, maintainible, and efficient interface.

Coherency:

If you implement a += operation, the user spects (Except in rare cases) the type provides a binary addition too. Implementing + with += provides this ensuring that the behavior of the two operations is coherent.

Maintainability:

You have implemented + using +=, so the code which really performs the addition is written only once. If you need to change the operation in the future you have to change one code only, and if it has a bug that bug is in one site only. Reducing code duplication is a good practice in general.

Efficiency:

The way the operator+() is written allows the compiler to easily elide copies, boosting the performance of the binary addition.

The idiom used is "copy first operand, operate on it, return the copy". So the compiler can easily perform a return value optimization (RVO). Also, it passes the first operand by value instead of copying the operand by hand inside the function. This allows the compiler to perform more copy elisions when the first operand is an rvalue (Let the compiler decide when and how to copy).

uchar
  • 2,552
  • 4
  • 29
  • 50
Manu343726
  • 13,969
  • 4
  • 40
  • 75
  • What the OP did is right. I agree that the usual way to do it is to implement `operator+` in terms of `operator+=`, but both approaches are "right". We do not know the context... – jbgs Jan 18 '14 at 14:24
  • @jbgs Agree. I have changed *No* to *Yes, but*. – Manu343726 Jan 18 '14 at 14:26
  • @Manu343726: You actually do **not** need `operator+` to be declared as `friend` here, since it only relies on the `public` interface of the class. – Matthieu M. Jan 18 '14 at 15:20
  • @MatthieuM. thats true. I was only providing the general methodology. – Manu343726 Jan 18 '14 at 16:08
  • 2
    @Manu343726: It actually also works in general. Compound operators need be members, but other operators rarely need to. – Matthieu M. Jan 18 '14 at 16:17
  • @MatthieuM. except if you use things like the Barton-Nackman trick to implement that operators, which is what I usually do by default. – Manu343726 Jan 19 '14 at 00:41
  • @Manu343726: Ah, but then that's a totally other requirement; and a different beast too. If executed correctly (such as with Boost.Operators) the `friend` operators are declared in a stateless base class, and since friendship is not inherited they need not be inspected for invariant corruption. – Matthieu M. Jan 19 '14 at 12:01
1

Yes you can do it your way:

BigNumber& operator +=(const BigNumber& other)
{
    *this=(*this) + other;
    return *this;
}

The usual approach is the opposite way:

// Note a is no const reference
BigNumber operator + (BigNumber a, const BigNumber& b)
{
    return a += b;
}

A reasoning for your approach might be memory allocation.