57

Given the following code snippet,

class Num
{
public:
    Num(int iNumber = 0) : m_iNumber(iNumber) {}

    Num operator+=(const Num& rhs)
    {
        this->m_iNumber = (this->m_iNumber + rhs.m_iNumber);
        return *this;
    }
private:
    int m_iNumber;
};

//===========================================================
int _tmain(int argc, _TCHAR* argv[])
{
    Num a(10);

    Num b(100);

    b += a;

    return 0;
}

I would like to know how to correctly overload the operator+=.

Questions:

  1. How to define the signature of this operator? Specially, what should be used for the return value?

  2. How to implement the function body?

  3. How to use this overload operator?

I have provided a solution as above but I have concerns that it is not correct.

Ziezi
  • 6,375
  • 3
  • 39
  • 49
q0987
  • 34,938
  • 69
  • 242
  • 387
  • @James, I searched through Google and didn't find one good resource to show me how to implement the operator+=. Also, I have seen some people use a "reference" as the return value of this function, but I could not figure out why and what the usage of that is. -- thank you – q0987 Jan 03 '11 at 04:04
  • A decent C++ book will tell you how to do it. Sometimes "searching through Google" is not enough; it's certainly not reliable. :) – Lightness Races in Orbit Jan 03 '11 at 04:16
  • 2
    @q0987 - As a side note, I think it is worth to mention, that if you already implementing the `operator+=` for your class, it is usually a good practice to implement the `operator+` as well, IN TERMS of the `operator+=`. See item 22 in the excellent More Effective C++ (version 1) by Scott Meyers. – Guy Avraham Apr 24 '18 at 08:25

6 Answers6

77

Returning by reference would be better

Num& operator+=(const Num& rhs){

      this->m_iNumber += rhs.m_iNumber;
      return *this;
}
Prasoon Saurav
  • 91,295
  • 49
  • 239
  • 345
  • 4
    Hello Prasoon, what is the benefit to return by reference and how could you use it? I assume that "return by reference" allows the user to change the internal data. thank you – q0987 Jan 03 '11 at 04:00
  • 9
    @q0987: The result of any assignment usually returns the variable which is leftmost in the assignment. If you return a reference, that's what you're actually doing. If you return a value, you're returning a *copy* of the leftmost assignment instead of the actual value. That is, `Num a(10); (a += Num(10)) = 100;` results in `a` having the content `20` instead of what some programmer might expect, `100`. – Billy ONeal Jan 03 '11 at 04:02
  • 5
    @q0987 : Furthermore returning by reference won't create a copy of the object (returning by value will) and so there won't be any call to the copy c-tor. However modern compilers would elide the copy in most cases. Read about RVO(Return Value Optimization). – Prasoon Saurav Jan 03 '11 at 04:02
  • 1
    If you don't return by reference you invoke copy constructors, temp copies, etc. Returning by reference WON'T allow the user to modify internal data that you haven't permitted through accessors to be modified. – JUST MY correct OPINION Jan 03 '11 at 04:03
  • should we also put a const at the beginning of the reference? , like: const Num& operator+=(const Num& rhs) {....} – M.SEL Nov 27 '19 at 17:00
  • 1
    Why can't the return-type be void? Shouldn't the function only assign a value to the attribute in the current instance of the class...? Why do we need to return a pointer to the instance? And if such, why pointer and not the object itself? EDIT: I think I got it.... in normal speech: just as the '+' operator returns the sum of the two, the '+=' should both: assign to the left operand and return the value it altered; that is, the leftmost value... if anyone thinks he could add anything relevant, please do – M.Ionut Mar 08 '20 at 16:50
  • I also think the `+=` should be void since the left hand object is the only one being updated, no need to return itself. – Maf Feb 25 '21 at 11:15
15

If you follow to this Wikibook you'll find these answers by example:

  1. Type& operator+=(const Type& right) is the correct signature.
  2. You did it right.
  3. You use an overloaded operator just like the plain operators, only with your type in place. That's kind of the point of the exercise. ;)

Note as an added point (which you did right) the compound assignment operators have to be member functions.

JUST MY correct OPINION
  • 35,674
  • 17
  • 77
  • 99
  • I didn't know this "the compound assignment operators have to be member functions" -- thank you for pointing out. – q0987 Jan 03 '11 at 04:09
  • Well, the operator needs detailed knowledge of your class' internals in most cases. By definition this pretty much requires it to be a member function. – JUST MY correct OPINION Jan 03 '11 at 05:13
  • 2
    Actually compound assignment operators can be non-member functions. This can be useful in situations where you can't provide a member function for some reason. For example enums (which is what I was searching for when I came across this). See the useful discussion on overloading here (http://stackoverflow.com/questions/4421706/operator-overloading/4421729#4421729) – BillyT2 Nov 11 '15 at 23:26
7

The signature of any of the assignment operators (operator= or operator @= for your favorite operator @) should be

Class& operator @= (const Class& rhs);

That is, the function takes its parameter by const reference (because it doesn't modify it), then returns a mutable reference to the object. The reason you return a non-const reference is because, for historical reasons, you can write code like this:

(a += b) += c;

This is by no means good style, but it works for ints and so you should endeavor to make it work for your types as well.

As for the body of your function, what you have there is perfectly correct. In general, though, you should be sure that the code works even if the parameter is the receiver object. For example, if you write something like

a += a;

This gets translated into

a.operator+= (a);

And so the code will operate with both the parameter and the receiver being the same object. This usually doesn't come up for compound assignment operators (usually only operator= needs to worry about this), but in some cases you can get burned if you're not careful.

Finally, you can use this operator += function just as you have been in the example code above. Any use of += automatically calls it.

Hope this helps!

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
  • 2
    Pedantic, picky point but we usually prefer '@' to '#' for arbitrary operators to avoid triggering 'comment mode' in syntax highlighters. :) – Lightness Races in Orbit Jan 03 '11 at 04:15
  • 1
    @Tomalak Geret'kal- Thanks for letting me know! I'll be sure to fix that in the future. – templatetypedef Jan 03 '11 at 04:18
  • I wonder why these operators (e.g. `operator+=`) aren't implemented by default when you implement the related operator (like `operator+`). You know, like what happens when you overload `operator<=>`. – flarn2006 Oct 12 '22 at 22:42
  • I could see some reasons for this. Perhaps creating a full copy of the object, which would be needed for `operator +`, would be extremely costly, or the object isn’t copyable. Or maybe you want the object to wave a Greek flag (`operator +=`) but not a Swiss one (`operator +`)? – templatetypedef Oct 14 '22 at 04:58
4

Your operator function could also be written as

Num& operator += (const Num& rhs)
{
   m_iNumber += rhs.m_iNumber;
   return m_iNumber;
}

*this->m_iNumber and m_iNumber by itself within a member function are the same and using the former format is more typing in my opinion.

alamoot
  • 1,966
  • 7
  • 30
  • 50
CnCPPcoder
  • 84
  • 5
3

Your example is completely correct: http://codepad.org/PVhQw9sc .

  1. You can define the return value to be whatever you want. If you wanted it to match what int does, it would need to return the type Num&, and return the value *this.
  2. You did it correctly.
  3. You also did that correctly.
Billy ONeal
  • 104,103
  • 58
  • 317
  • 552
  • Hello Billy, I have similar comments as the one I gave to @Prasoon. For example, for the INT, how can you use += chaining or assign a new value to the returned value of operator+=? thank you – q0987 Jan 03 '11 at 04:02
  • @w0987: Answered your question there :) – Billy ONeal Jan 03 '11 at 04:02
3

Write the body like you did. Use the operator like you did. The operator should return a reference to allow chaining.

See here.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055