Whenever we call a member function in association with an object, the object’s address is implicitly passed as a hidden first argument received in the called member function using a special pointer known as this pointer. The this pointer contains the address of the object that generates the call. It is implicitly defined in each member function, and its data type is that of a pointer to the class type.
In below programs, we saw that the member functions of the objects can manipulate data members directly without using the member access operator. Consider the following member function definition in a class rectangle.
void rectangle::setdata(int i,int j) { l = i; b = j; }
We know that if the member function setdata() of class rectangle is called for the object r1, the data members l, b manipulated in setdata() are data members of r1 object. If the object r2 generates the call to the function setdata(), the data members accessed are those of r2 object. So, how does the modification made in the member function setdata() are reflected back to the data members of the object that generates the call. This is done using this pointer.
#include<iostream.h> #include<conio.h> class rectangle { private: int l,b; public: void setdata(int i,int j) { cout<<"Address of object that generatesarea() call "<<this<<"\n"; cout<<"Address of object that generatessetdata() call: "<<this<<"\n"; this->l=i; //equivalent to l=i this->b=j; //equivalent to b=j } void area() { cout<<"Address of object that generatesarea() call "<<this<<"\n; cout<<"Area "<<this->l*this->b; } }; int main() { clrscr (); rectangle r1; r1.setdata(l0,15}; r1.area(); getch(); return 0; } Output Address of object that generates area() call = Ox8fc0fff2 Address of object that generates area() call = Ox8fc0fff2 Area = 150
Explanation: When the member function setdata() is called in association with object r1 on executing the statement
r1.setdata(l0,15);
then in addition to passing values 10 and 15, the address of object r1 that generates the call is automatically passed to the function setdata() within the definition of the member function setdata(). A this pointer variable of type rectangle is impilictly defined in setdata() which receives the address of the passed object.
The first statement in the setdata () member function definition displays the address of the object that generates the call using this pointer. The remaining statements,
this->l=i; this->b=j;
refer to the data members l and b of the object r1 explicitly using this pointer. This is equivalent to the statements that are already being used in which this pointer is implicitly used
l = i; b = j;
As data members are manipulated using this pointer within function definition, so any modification made are reflected back to the object that generates the call.
Similarly the statement in main(),
r1.area();
on execution, calculates the area of rectangle by accessing the data members l and b using this pointer.
When to Use this POINTER
Some of the uses of this pointer are:
(a) The use of this pointer is more visible in practical situations where we want to return an object that generates the call from the member function. Consider an example in which we want to compare the performance of two student objects on the basis of their percentage. In order to implement this, we defined a class student having private data members rollno, name, percent and public member functions read(), show() and compare(). The purpose of compare() member function is to compare two student objects on the basis of their percentage of marks and return the object with greater percentage which may be the object passed explicitly as argument or the object that generates the call. The complete program is shown below
#include<iostream.h> #include<conio.h> class student { private: int rollno; char name[20]; double percent; public: void read() { cout<<"Enter student's rollno, name and percentage = "; cin>>rollno>>name>>percent; } void show() { cout<<"Name = "<<name; cout<<"\nRollno = "<<rollno; cout<<"\nPercentage = "<<percent; } student &compare(student &ss2) { if(percent>=ss2.percent) return *this; //returing object that generates call </span> <span style="color: #000000;"> else return ss2; } }; int main() { clrscr(); student s1,s2,s3; cout<<"Enter student1 details"; s1.read(); cout<<"Enter student2 details\n"; s2.read(); s3=s1.compare(s2); cout<< "Intelligent student detail is \n"; s3.show(); getch(); return 0; } Output : Enter student1 details Enter student's rollno, name and percentage= 1215 anil 53 Enter student2 details Enter students rollno, name and percentage = 1316 kapil 62 Intelligent student details's Name = kapil Rollno = 1316 Percentage = 62
Explanation: In the main(), the statement student s3 = s1.compare(s2); invokes the function
student &compare (student &ss2){...}
(a) This function returns the object that generates the call by reference using the statement return * this; if the percentage of s1 object is greater than or equal to that of s2 object, otherwise the object s2 passed explicitly is returned. One should remember that *this used in the return statement returns the object it is pointing to. The returned object is received in main() by object s3, which is then displayed.
(b) Another use of this pointer is to perform cascaded member function calls in which multiple functions can be invoked in a single statement. For example, if we extend the above program for comparing the percentage of three students, then the same function compare() can be invoked separately in a single statement as follows
s4 = s1.compare(s2).compare(s3);
The cascaded function calls are executed from left to right as the associativity of dot(.) operator is from left to right. So, s1.compare(s2); is invoked first, which returns the appropriate student’s object by reference. The returned object is further used to invoke the function compare() that finally returns the student’s object with a maximum percentage. This
(c) this pointer is sometimes useful for removing ambiguity when the name of parameters used member function are same as l at of data members used.
If, in the previous program, the name of the data members l and b is the same as that of parameters l and b used, then the ambiguity can be resolved using this pointer.
(d) this pointer is also used when overloading an operator as a member function. We have seen that while overloading a binary operator as a member function, the function will have only one parameter that receives the object on the right side of the operator. How does the overloaded operator member function access the object on the left side of the operator? It is accomplished implicitly using this pointer which contains the object’s address on the left side of the operator that generates the function call.