When you should make explicit use of the 'this' pointer

While learning C++, sooner or later you will run into the this pointer. This article explains its use on three groups of examples, namely:

What is the this pointer

To illustrate the concept of the this pointer we are going to use a class called Account. For the moment the class has only one member variable 'amount'. Apart from the standard get and set method, notice an extra method in the header called getAddress(), which returns the this pointer.

#ifndef ACCOUNT_H
#define ACCOUNT_H

class Account
{
public:
    void setAmount(double amount);
    double getAmount() const {return this->amount;}
    Account* getAddress() {return this;}
private:
    double amount;
};

#endif // ACCOUNT_H
#include "account.h"

void Account::setAmount(double a){
    amount = a;
}

To show you the meaning of this pointer, I am going to instantiate one Account object with the use of the default constructor and call its getAddress() method, as illustrated in the main.cpp:

#include <iostream>
#include "account.h"

int main()
{
    Account ac;
    std::cout << ac.getAddress() << '\n';
    return 0;
}

You can see the output of the program below.

0x28ff38

The program outputs an address (most probably you are going to get a different address than me, since you are using a different computer). This pointer gives us an address of an instantiated object! It gives us a way to refer to the instantiated object itself.

Note: this pointer gives you an address of an object, while *this gives you the object residing at the address this.

Disambiguation of member variables and method parameters

Now that we shed a bit of light on the 'this' pointer, we are going to look at its first use, i.e. to distinguish between member variables and method parameters. We are going to do that with the help of the method setAmount(double).

Notice the current implementation of the setAmount() method. To distinguish between the method parameter and the member variable, we are using the name 'a' for the method parameter and the name 'amount' for the member variable.

void Account::setAmount(double a){
    amount = a;
}

Illustration of the setAmount() method

Since we now know a bit more about the 'this' pointer, we are going to write the setAmount() method in a different way. In this new approach, we are going to rename the method parameter 'a' to 'amount'. Of course, now we have a problem because the method parameter has the same name as the member variable. How are we going to solve this? We are going to use the pointer this to distinguish between them. The new 'name' of the member variable is this->amount. You can see the new method below:

void Account::setAmount(double amount){
    this->amount = amount;
}

Illustration of the setAmount() method

How useful! As a result, we do not have to come up with different names for method parameters and member variables for set methods.

Method chaining

To show you the next use of the this pointer we are going to introduce an extra member variable called the interest rate and the corresponding set method. We are also going to add a method called addAnnualInterest(). The method increases the value of the current amount by the annual interest according to the following formula:

amount = amount * (1 + interest rate)

The header and the source file are shown below. Notice that the addAnnualInterest() method returns a reference to the modified Account object, hence the line 'return *this'.

#ifndef ACCOUNT_H
#define ACCOUNT_H

class Account
{
public:
    void setAmount(double amount);
    double getAmount() const {return this->amount;}
    void setInterestRate(double interestRate);
    Account& addAnnualInterest();
private:
    double amount;
    double interestRate;
};

#endif // ACCOUNT_H
#include "account.h"

void Account::setAmount(double amount){
    this->amount = amount;
}

void Account::setInterestRate(double interestRate){
    this->interestRate = interestRate;
}

Account& Account::addAnnualInterest(){
    this->amount = this->amount*(1 + this->interestRate);
    return *this;
}

Why do we return a reference to the modified Account object, when we could have simply declared the addAnnualInterest() method as void, increased the amount and returned nothing at all? The reply is because by returning a reference we have the possibility of method chaining.

You can see the example of method chaining in the main.cpp below. Because the method addAnnualInterest() returns a reference to the modified object, we can now call the same method multiple times in a chain and modify the object by the amount of interest after several years (in this case three method calls = three years). If we had declared the method as void, we would not have been able to perform method chaining.

#include <iostream>
#include "account.h"

int main()
{
    Account ac;
    ac.setAmount(1000.0);
    ac.setInterestRate(0.1);
    ac.addAnnualInterest().addAnnualInterest().addAnnualInterest();
    std::cout << ac.getAmount() << '\n';
    return 0;
}

The output of this program is 1331, which was internally computed in the following way:

amount1 = 1000*(1+0.1) = 1100
amount2 = 1100*(1+0.1) = 1210
amount3 = 1210*(1+0.1) = 1331

Operator overloading

The last use of the 'this' pointer that we are going to look at is operator overloading. Just like with method chaining, our aim is to increase the amount on the account after several years by the amount of annual interest. However, unlike in the case of method chaining, we are not going to introduce addAnnualInterest() method, but rather overload the operator *= to accomplish the same thing.

Notice the header and source file below. As we are going to use a general multiplier, we removed the member variable interest rate, Moreover, we added operator*=(double multiplier) that takes the current amount, multiplies it and returns a reference to the modified object (return *this). This is performed in a similar manner to the addAnnualInterest() method. The multiplier is simply:

multiplier = 1 + interest rate
#ifndef ACCOUNT_H
#define ACCOUNT_H

class Account
{
public:
    void setAmount(double amount);
    double getAmount() const {return this->amount;}
    Account& operator*=(double multiplier);
private:
    double amount;
};

#endif // ACCOUNT_H
#include "account.h"

void Account::setAmount(double amount){
    this->amount = amount;
}

Account& Account::operator*=(double multiplier){
    this->amount = this->amount * multiplier;
    return *this;
}

The main.cpp below illustrates the use of the operator*=.

#include <iostream>
#include "account.h"

int main()
{
    Account ac;
    ac.setAmount(1000.0);
    ac*=1.1;
    ac*=1.1;
    ac*=1.1;
    //((ac*=1.1)*=1.1)*=1.1;
    std::cout << ac.getAmount() << '\n';
    return 0;
}

Similarly to the method chaining example the output of the program is 1331 (amount with interest after three years), which we got in the following way:

amount1 = 1000*1.1 = 1100
amount2 = 1100*1.1 = 1210
amount3 = 1210*1.1 = 1331

The commented section shows that it is also possible to do this in one row, however we shall not forget the parentheses.


Latest update: 22.04.2016
Created: 2013
© Walletfox.com, 2017