1

I tried to consult the book and the reason I found there is that the prototype of the operator function to overload << operator is:

friend ostream& operator<<(ostream&, const className&);

Now consider the following statement:

cout << myRectangle << yourRectangle;

This statement is equivalent to the statement:

operator<<(operator<<(cout, myRectangle), yourRectangle); //Line A

because the associativity of the operator << is from left to right. To execute the previous statement, you must first execute the expression:

cout << myRectangle

that is, the expression:

operator<<(cout, myRectangle)

After executing this expression, which outputs the value of myRectangle, whatever is returned by the function operator << will become the left-side parameter of the operator << (that is, the first parameter of the function operator<<) in order to output the value of object yourRectangle (see the statement in Line A). The left-side parameter of the operator << must be an object of the ostream type, so the expression: cout << myRectangle must return the object cout (not its value) to the left side of the second operator << in order to output the value of yourRectangle. Therefore, the return type of the function operator<< must be a reference to an object of the ostream type.

That means you cannot pass an object by value as an argument where the formal parameter takes it by reference. So it makes sense to me why do we return by reference when overloading << operator. But where I get confused is in this statement:

tempRectangle = myRectangle + yourRectangle + anyRectangle;

According to the precedence and associativity of the operators, the compiler will first execute:

myRectangle + yourRectangle

Which is equivalent to:

myRectangle.operator+ (yourRectangle); // Line B

► Here comes my first confusion that after executing line B, it will return the object by value (which is then to be added by the third object, i.e. anyRectangle). So how do you write this addition in terms of line B (because we do not have any name to that object which is returned by value, so how does it perform this addition).

► Second confusion is that after adding all the three objects in this statement:

tempRectangle = myRectangle + yourRectangle + anyRectangle;

we have a returned-by-value object, which is then to be passed to operator= function to assign it tempRectangle. Now this is the same case as it happened it << operator. As the prototype of operator= function is :

className operator+(const className&) const;

This function also has a reference parameter. But we passing object by value as an actual parameter (in overloading << operator, we were having return by reference because we had to pass it to reference parameter which could not return by value object so why are we not doing the same here, i.e return by reference).

Bilal Sheikh
  • 119
  • 7

1 Answers1

0

As mentioned in a comment operator= should return a reference. On the other hand operator+ is different because in

auto c = a + b;

The operator+ typically leaves both operands unchanged und a new object is created as result. For example

struct foo {
    int value;
    foo operator+(const foo& other) const {
        foo result;
        result.value = value + other.value;
        return result;
    }
};

If you chain operator+ as in

auto c = (a + b) + c;

Then operator+(c) is neither called on a nor b but on the result of a+b.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
  • But how does the result of addition is getting passed to operator= ? Because operator= takes the parameter (object) by reference but we are passing it returned by value object. I am confused here :( – Bilal Sheikh Jul 06 '20 at 12:17
  • @BilalSheikh it seems you have a general confusion about references. You can pass a object to a function that expects a reference, no problem with that and I suppose you already did that several times – 463035818_is_not_an_ai Jul 06 '20 at 12:20
  • look at this: `int increment(int &x) { return (++x);}` ,now would this work if we call it that way `int y = 0;` `int num = increment (increment (y));`? – Bilal Sheikh Jul 06 '20 at 12:32
  • my understanding says that the prototype should be `className& operator= (const className);` and not be `className& operator= (const className&);` – Bilal Sheikh Jul 06 '20 at 12:35
  • @BilalSheikh no that wouldnt work, but frankly I don't quite understand how that is related to return types of operators – 463035818_is_not_an_ai Jul 06 '20 at 12:36
  • @BilalSheikh then your understanding is wrong – 463035818_is_not_an_ai Jul 06 '20 at 12:36
  • you are mixing up too many things at once. Now you are asking for the argument type. Why do you think it should be pass by value rather than a reference? – 463035818_is_not_an_ai Jul 06 '20 at 12:39
  • I am just not getting where am I stuck. any advice :/ – Bilal Sheikh Jul 06 '20 at 12:40
  • @BilalSheikh the duplicate and https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list – 463035818_is_not_an_ai Jul 06 '20 at 12:42
  • I think it should be pass by value because if you look at this piece of code `int increment(int &x) { return (++x);}` `int y = 0;` `int num = increment (increment (y));` it won't work but it would work if we make this little change `int increment(int x) { return (++x);}` `int y = 0;` `int num = increment (increment (y));` reason: function increment is a return by value function and we cannot make it as an actual parameter where formal parameter accepts it by reference. Thats why it was not working in the first case. BTW return a variable by value and returning object by value are same thing? – Bilal Sheikh Jul 06 '20 at 12:49
  • @BilalSheikh " it should be pass by value because" that completely depends on what the function is supposed to do, which you didnt say. – 463035818_is_not_an_ai Jul 08 '20 at 09:31