"THIS" Pointers and function calls

I'm doing some pointer exercises from GeeksforGeeks, and I'm having trouble understanding what (*this) does, in the following code.

What exactly is (*this) in &setX and &setY referring to?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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;
}
this gives you a pointer to the object that the function was called on.

In your program you call setX on obj1 so inside setX this gives you a pointer to obj1.

The asterisk * is the dereference operator. It gives you a reference to whatever the pointer points to.

So the setX and setY functions return a reference to the object on which it is called. obj1.setX(10) returns a reference to obj1 so that allows you to call another member function on the returned reference by just adding another function call.

If the function had not returned a reference to the object it would not be possible to call the functions after each other like you do on line 18. You would instead have to split it over two statements, repeating obj1.
1
2
obj1.setX(10);
obj1.setY(20);


This is also how the << operator works to make it possible to chain multiple << operator after each other.

 
cout << "x = " << x << " y = " << y << endl;
is the same as
 
((((cout << "x = ") << x) << " y = ") << y) << endl;

First cout << "x = " runs and returns a reference to cout.
Second the << operator is applied to the returned reference to print x. This also returns a reference to cout.
And so on...
Last edited on
See also http://stackoverflow.com/questions/2476381/c-constructor-initialization-list-strangeness
That introduces "member initialization list".

You have
1
2
3
4
5
Test (int x = 0, int y = 0)
{
  this->x = x;
  this->y = y;
}

Which is close to
1
2
3
4
5
6
7
Test (int x = 0, int y = 0)
: x(), y() // initialization
{
  // assignment
  this->x = x;
  this->y = y;
}

But why initialize and assign, when mere initialization is sufficient?
1
2
3
4
Test (int x = 0, int y = 0)
: x(x), y(y) // initialization
{
}

The link explain why that is not ambiguous, but one could use other names for "clarity":
1
2
3
4
Test (int a = 0, int b = 0)
: x(a), y(b) // initialization
{
}


A pointer is a variable that stores a value (just like all variables).
The value stored by pointer is a memory address.
The pointer has (unary) dereference operator * that is used to access the object (variable) that is at the memory address.
A pointer can have a memory address that does not contain object of correct type. Such pointer has invalid value and a dereference leads to undefined result.
Memory address 0 is always invalid. Easy to test for. nullptr is a named constant that has type pointer and value 0.


Python has equivalent of 'this'. It is more explicit and is named 'self'. http://stackoverflow.com/questions/2709821/what-is-the-purpose-of-self-in-python


Only members of class can access the private members of the class. A struct, by default, has public members. Therefore, as an example:
1
2
3
4
5
6
7
8
9
10
11
12
13
struct Foo {
  int x;
  void setX( int x ) { this->x = x; }
};

void setX( Foo * this, int x ) { this->x = x; }

int main() {
  Foo obj;
  obj.setX( 7 );  // member function
  setX( &obj, 42 ); // stand-alone function
  return 0;
}

Do you notice the similarity of the two approaches?

The C++ is based on C and C has structs, but no member functions. C has to use stand-alone functions for everything. C++ has member functions in order to implement access control, and it implicitly provides the 'this' for them. Granted, not every member function needs the this.

What exactly is (*this) in &setX and &setY referring to?

The liberal use of whitespace ...
Not "in &setX and &setY". The names of the functions are setX and setY, or to be more precise Test::setX(int) and Test::setY(int).
1
2
3
4
5
6
7
8
9
10
11
12
Test &setX(int a);
// is same as
Test&setX(int a);
// is same as
Test& setX(int a);
// is same as
Test & setX(int a);
// is same as
Test &                    setX   (int a);
// is same as
Test &
setX(int a);

In every case, one should read (approximately) from right to left:
The 'setX' is a name of a function that takes one integer argument by value and returns a reference to an object that has type Test.
The amount of whitespace (when not syntactically critical) is a matter of style.
Last edited on
thanks a bunch Keski and Peter... I thought I had pointers nailed down, but it seems pointers and addresses within classes is another beast altogether
it seems pointers and addresses within classes is another beast altogether

No, not really.

Depends on how one sees things though; one could miss details and think that "all people from continent X look the same", or let superficial differences cloud judgement "no two pints of beverage Y taste the same" (when drunk in rapid succession; not recommended).
Topic archived. No new replies allowed.