confusing output

Below given program prints x = 10 y = 0

#include<iostream>
using namespace std;

class Test
{
private:
  int x;
  int y;
public:
  Test (int x = 0, int y = 0) { this->x = x; this->y = y; }
  Test setX(int a) { x = a; return *this; }
  Test setY(int b) { y = b; return *this; }
  void print() { cout << "x = " << x << " y = " << y << endl; }
};

int main()
{
  Test obj1;
  obj1.setX(10).setY(20);
  obj1.print();
  return 0;
}

but if we replace

Test setX(int a) { x = a; return *this; }
Test setY(int b) { y = b; return *this; }

with

Test &setX(int a) { x = a; return *this; }
Test &setY(int b) { y = b; return *this; }

output is x = 10 y = 20 Can anyone explain why this is happening?


When you return a plain object rather than a reference, you're returning a copy of the object on which you called the method. setY acts on that copy (which is a temporary), then the copy is destructed.

When you return a reference, all the calls operate on the same object, so you get the behavior you're looking for.


The first call to setX() returns a temporary copy of obj1 and the call to setY() modifies the temporary. Subsequent call to print() displays the state of obj1 and since in obj1 the y member variable was never modified it remains zero.

When you replace the return types with references, no temporary copy is made the both calls to setX() and setY() operate on obj.


Lets go back to basis about object oriented programming.

Lets use a metaphor - say a bus.

A bus has certain properties that can be changed - e.g. fuel.

So if you have a function (top up the fuel) you do not need a new bus that is exactly the same as the last one bit with a fuel tank that is full.

So going back to the original question.

Test setX(int a) { x = a; return *this; }

should read

void setX(int a) { x = a; }

etc.

You have the same object but the fuel may be topped up (or x in this case)