Section 3 - This

7A.3.1 The Implied "this"

Pretty soon we are going to give the full definition of Rectangle.  Let's consider the definition of the instance method setWidthHeight(). We might try it like so:

bool Rectangle::setWidthHeight(double w, double h)
{
if ( w<=0 || h<=0 )
{
// don't allow negative width or height
return false;
}
else
{
width = w;
height = h;
return true;
}
}

We called the formal parameters w and h. Not very informative (I deduct points for this sort of poor variable or object naming). Really, what we are passing in is the width and height of the rectangle. So why don't we call these parameters width and height?  We could try:

bool Rectangle::setWidthHeight(double width, double height)
{
if ( width<=0 || height<=0 )
{
// don't allow negative width or height
return false;
}
else
{
width = width;    // oops!
height = height;
return true;
}
}

See what happened? We named the formal parameters the same as the instance variables. Before, when we used the term width inside an instance method we meant the private data width of the calling object. But now we have a parameter with the same name, so there is ambiguity.

Recall that parameters are really just ordinary local variables or object references. They are very similar to the variables or objects declared inside the function, the only difference being that parameters get assigned values automatically when the function is called (via the arguments passed in through the function call). Now, let's recall a fact about any local variable (be it a parameter or ordinary variable defined in the function).

When we declare a local variable, if it has the same name as an instance member, this local variable hides or shadows the instance member throughout the method definition.

What this means is that if we use the term width inside our newly formed method, we would be referring to the local width (the parameter), not the member width.

But what if we want to name the formal parameter using the word width and also refer to the member using the same word, width, later in the method? There is a special reference identifier called "this" that all instance methods can use. This can be used to access any of the instance members by dereference. So, even though the formal parameter width shadows the member width, making it seem inaccessible, we can still "get at" that member using the "this->" notation:

this->width = width;
this->height = height;

Now we are safe. The LHS, this->width, refers to the member width of the calling object.  The RHS, width, refers to the formal parameter width of that same name.

Now, we can name formal parameters the same as members if it makes sense to do so and still have a way to get at the members.   This arrow notation, ->,  is pervasive in C++ and is not restricted to the word "this" as in "this->".  This ("this->") is simply the first situation in which it occurs.  It is similar to the dot notation, but we'll have to put off the full explanation for a while.

Here is how the method will look, once we have used this improved notation:

bool Rectangle::setWidthHeight(double width, double height)
{
if ( width<=0 || height<=0 )
{
// don't allow negative width or height
return false;
}
else
{
this->width = width;
this->height = height;
return true;
}
}

We recently learned that when we enter any instance method, some object must have been used to get us there, and that object was called the "this" object.  In main(), for example, any hypothetical member function-calls we might invoke, like fido.bark() or account_213.Balance() or maryann.ChangeZipCode(), all required objects to call these methods.  The word fido or account_213or maryann each represents the "this" object that initiated the function call.  Well, that is the same "this" that I'm talking about here!  When you get inside the method definition, you can't know which object did the call exactly.   It might be fido, or maryann or account_213.  So we use the keyword "this->" inside that method definition if we want access to the calling object for some reason without actually knowing that object's specific name.  Now I'm telling you that you can use the this notation to get at the object's members whether or not they are hidden by local variables.

Even if there is no local variable hiding an instance member, we can optionally place the "this->" keyword in front of the instance member (or instance method) while inside an instance method definition.  This is a complex sentence, so read it again, then look at the following example in which we first refer to an instance method clearSocSec() without the "this->" in front (old way), and next see it used with the "this->" attached  (new way) .

Recall this instance method:

// ------- Employee::getOlder -------
bool Employee::getOlder()
{
if (age++ > 147 )
{
clearSocSec();
return false;
}
else
return true;
}

Above, we are implicitly calling the clearSocSec() method using the this object that got us into getOlder() in the first place.  We could use the alternate syntax if it makes things clearer:

// ------- Employee::getOlder -------
bool Employee::getOlder()
{
if (age++ > 147 )
{
this->clearSocSec();
return false;
}
else
return true;
}

I'll take this opportunity to point out that getOlder() is a method that modifies private data. This makes it a mutator even if it does not bear the time-honored name setSomething().  As a mutator, it must not do input or output, and so it returns a bool that the client can inspect and, based on the outcome, do any desired output.  See the full example from last time to reinforce how that was handled.