Qingquan-Li / blog

My Blog
https://Qingquan-Li.github.io/blog/
132 stars 16 forks source link

C++ "this" Pointer #251

Open Qingquan-Li opened 1 year ago

Qingquan-Li commented 1 year ago

The this pointer is a built-in pointer that every class has. It is passed as a hidden argument to all nonstatic member functions, and it always points to the instance of the class making the function call.

For example, if student1 and student2 are both StudentTestScores objects, the following statement causes the getStudentName member function to operate on student1:

cout << student1.getStudentName() << endl;

Likewise, the following statement causes getStudentName to operate on student2:

cout << student2.getStudentName() << endl;

When getStudentName is operating on student1, the this pointer is pointing to student1. When getStudentName is operating on student2, the this pointer is pointing to student2. The this pointer always points to the object that is being used to call the member function.

1. Basic Usage of this Pointer:

// A common use case is when a member function parameter
// has the same name as a member variable.

class MyClass {
private:
    int value;

public:
    void setValue(int value) {
        // Typical way to set member variable
        // value = value;

        // Using 'this' can sometimes be used for clarity, especially
        // in scenarios where local variables or parameters might have
        // the same name as member variables.
        // By using this->, you're making it clear that you're referring to
        // the member variable and not the parameter.
        this->value = value;
    }

    int getValue() const {
        // Typical way to access member variable:
        // return value;
        // Or explicitly using 'this':
        return this->value;
    }
};

2. To Return the Current Object by Reference

// Useful in situations like when overloading certain operators or creating a chain of member function calls.

#include <iostream>

class ChainExample {
private:
    int data;

public:
    /**
     * Function to set the data member
     * @param d
     * @return a reference to an object of type ChainExample
     */
    ChainExample& setData(int d) {
        this->data = d;
        // Returns a reference to the current object.
        //The `this` pointer points to the object on which the member function is called (current object).
        //When you dereference the `this` pointer using `*this`, you get the current object itself.
        //Objects (like *this) can be used to initialize or assign to references.
        //A reference is an alias for another variable, providing an alternative name to access the same
        //underlying memory location.
        return *this;
    }

    /**
     * Function to increment the data member
     * @return a reference to an object of type ChainExample
     */
    ChainExample& increment() {
        this->data++;
        return *this;  // Returns the current object
    }

    /**
     * Function to get the data member
     * @return the data member
     */
    int getData() const {
        return data;
    }
};

int main() {
    ChainExample obj;
    obj.setData(5).increment().increment();
    std::cout << obj.getData() << std::endl; // 7
    return 0;
}

3. Use this pointer to access the calling object's data in operator overloading

The this pointer points to the entire object for which the member function (where this is being used) is called. Through the this pointer, you can access all members (public, protected, and private) of that object.

#include <iostream>

class MyNumber {
private:
    int value;
public:
    // Default constructor. Initializes the value of the object to 0
    // MyNumber() : value(0) {}

    // Parameterized constructor. Initializes the value of the object to val
    // MyNumber(int val) : value(val) {}
    // Same as:
    MyNumber(int val) {
        value = val;
    }

    /**
     * Overloads the + operator to add two MyNumber objects.
     *
     * This member function returns a new MyNumber object whose value
     * is the sum of the calling object's value and the passed object's value.
     *
     * @param other: A constant reference to another MyNumber object
     *               that we want to add to the current object.
     *
     * @return: Returns a new MyNumber object representing the sum
     *          of the current object and the passed object.
     */
    MyNumber operator+(const MyNumber& other) const {
        // The 'this' pointer points to the calling object.
        // In the context of this overloaded operator, the calling object is the one
        // on the left side of the + operator.
        // For example, in the expression 'a + b', if 'a' and 'b' are MyNumber objects,
        // 'a' is the calling object and 'b' is the 'other' object.

        // 'this->value' gets the value of the calling object.
        // 'other.value' gets the value of the 'other' object.

        // Create a new MyNumber object with the combined value.
        // return MyNumber(value + other.value);
        // Using this-> to make it clear that we are accessing the value of
        // the calling object (the member variable):
        return MyNumber(this->value + other.value);
    }

    void display() const {
        std::cout << "Value: " << value << std::endl;
    }
};

int main() {
    // Create two objects of type MyNumber with parameterized constructors
    MyNumber num1(5); // Initializes the num1 object to 5
    MyNumber num2(10); // Initializes the num2 object to 10
    MyNumber sum = num1 + num2;  // Calls the overloaded + operator
    sum.display();  // Displays "Value: 15"

    // Create two objects of type int
    int num3 = 5;
    int num4 = 10;
    int sumOfNum3AndNum4 = num3 + num4;  // Calls the built-in + operator
    std::cout << sumOfNum3AndNum4 << std::endl;  // 15
    return 0;
}