user366312
user366312

Reputation: 16896

Which variation of C++ Operator Overloading should I use? And, why?

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?

Upvotes: 3

Views: 310

Answers (5)

johnsyweb
johnsyweb

Reputation: 141790

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

Upvotes: 4

Kiril Kirov
Kiril Kirov

Reputation: 38163

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.

Upvotes: 10

Summer_More_More_Tea
Summer_More_More_Tea

Reputation: 13356

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.

Upvotes: 4

AusCBloke
AusCBloke

Reputation: 18492

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.

Upvotes: 0

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.

Upvotes: 2

Related Questions