3

Here 3 variations of the overloading of addition operator (+) are given.

Which variation should I use and why?

class MyClass {
    int myInteger;
    double myDouble;
    public:
        MyClass(int i, double d) {
        myInteger = i;
        myDouble = d;
    }

    // Variation - 1
    //--------------
    MyClass operator +(MyClass rhsObj) {
        return MyClass(this->myInteger + rhsObj.myInteger, this->myDouble + rhsObj.myDouble);
    }

    // Variation - 2
    //--------------
    MyClass &operator +(MyClass &rhsObj) {
        rhsObj.myInteger = this->myInteger + rhsObj.myInteger;
        rhsObj.myDouble = this->myDouble + rhsObj.myDouble;

        return rhsObj;
    }

    // Variation - 3
    //--------------    
    MyClass &operator +(MyClass &rhsObj) {
        this->myInteger = this->myInteger + rhsObj.myInteger;
        this->myDouble = this->myDouble + rhsObj.myDouble;

        return *this;
    }
};


int main() {
    MyClass objOne(10, 10.5);
    MyClass objTwo(20, 20.5);

    MyClass objThree = objOne + objTwo;
}

What should be the case of Assignment Operator (=)? Which variation should it use?

0x499602D2
  • 87,005
  • 36
  • 149
  • 233
user366312
  • 17,582
  • 55
  • 198
  • 392

5 Answers5

10

Depends on what you need.

First, about you versions - obviously

  • "Variation - 1" creates new object, without touching the two operands.
  • "Variation - 2" stores the result in the second operand
  • "Variation - 3" stores the result in the first operand in "this".

Most likely, Variation - 1 is the most preferred.

Why? Because of the side effects. If you see an expression like:

a = b + c;

whatever is the type of a, b and c, what you would think? I would think, that a is the sum of b and c AND b and c are untouched, I mean - with the old values.
Suppose, for example:

a = 5;
b = 6;
c = a + b;

Would you expect, that a or b will become 11 after the sum? (which will happen if you chose variation 2 or 3). Of course, you cannot overload operator+ for int, but it's just an easy and intuitive example.


One performance improvement: in your variation 1, instead of

MyClass operator+(MyClass rhsObj)

I would use

MyClass operator+(const MyClass& rhsObj)

This way you'll avoid one additional copy + you will tell the "client", using your code, that you don't change rhsObj at all, but just use its value.

Kiril Kirov
  • 35,473
  • 22
  • 102
  • 177
4

There are subtle differences between these three +'s

The first variation:

// Variation - 1
//--------------
MyClass operator+(MyClass rhsObj)
{
    return MyClass(this->myInteger + rhsObj.myInteger, this->myDouble + rhsObj.myDouble);
}

takes an object of MyClass as input, which means a copy of rhsObj is passed into the + remaining the original object rhsObj unchanged. This override returns a newly created object of MyClass.

The second variation:

// Variation - 2
//--------------
MyClass & operator+(MyClass & rhsObj)
{
    rhsObj.myInteger = this->myInteger + rhsObj.myInteger;
    rhsObj.myDouble = this->myDouble + rhsObj.myDouble;

    return rhsObj;
}

takes a reference to rhsObj as input and the rhsObj is updated in the method.

The last variation

// Variation - 3
//--------------    
MyClass & operator+(MyClass & rhsObj)
{
    this->myInteger = this->myInteger + rhsObj.myInteger;
    this->myDouble = this->myDouble + rhsObj.myDouble;

    return *this;
}

also takes a reference to rhsObj as parameter, but rhsObj is not modified inside the method. Instead, the MyClass object on which the + is invoked updated.

Summer_More_More_Tea
  • 11,342
  • 10
  • 45
  • 76
4

You really want variations on one and three here.

Users of MyClass will expect it to follow The Principle of Least Astonishment and would never expect to see the right-hand-side modified as a result of addition. Using const more will enforce this and will also serve as documentation. If you wish to modify the left-hand-side, use +=. Like so:

// Plus: Modify neither the left nor the right
//--------------
MyClass operator +(const MyClass& rhsObj) const
{
    return MyClass(myInteger + rhsObj.myInteger, myDouble + rhsObj.myDouble);
}

// Increment: Modify the left
//--------------
MyClass& operator +=(const MyClass& rhsObj)
{
    myInteger += rhsObj.myInteger;
    myDouble += rhsObj.myDouble;

    return *this;
}

Demo: http://ideone.com/8oarA

Johnsyweb
  • 121,480
  • 23
  • 172
  • 229
2

Conceptually, you want to return a new pair, so in your case the first variant is perhaps better.

Or perhaps you want to return one of the argument, but then I find confusing the name of the operator. It could be better += for the third variant.

Basile Starynkevitch
  • 1
  • 16
  • 251
  • 479
0

I would think variation 1 would be best for mainly one reason: if you had just the statement lhs + rhs;, would you expect/want lhs or rhs to be modified? I know that I probably wouldn't in most (all?) cases.

Therefore that rules out variations 2 and 3.

AusCBloke
  • 16,716
  • 6
  • 38
  • 44