The this Pointer in Member Functions
Let's look back at our first printElephant function. It currently accesses a (public!) data member, name_, but perhaps this data member should have been private, in which case printElephant would need to be a member function for the Elephant class, Elephant::print.
Let's compare the two approaches. On the left we have the global function, and on the right the member function (which would also need to be declared in the class definition).
void printElephant(const Elephant* ePtr) {
cout << "Elephant named " << ePtr->name_ << endl;
}
which is called with
printElephant(&charlie);
void Elephant::print() const {
cout << "Elephant named " << name_ << endl;
}
which is called with
charlie.print();
Both pieces of code do the same thing, and our example use has both of them operating on the elephant charlie. But one thing is interesting: an argument is passed into the function in the left-hand version, but the right-hand version shows a function that takes no arguments.
How does the member function know what object it's running on?
Magic?
There is no magic here. Just hidden machinery.
That's what my people tell more primitive beings about transporter technology. Sometimes.
Behind the scenes, when we write any member function, it's as if the function has a hidden extra argument. The name and type of the hidden extra argument is
const Elephant* thisforconstmember functionsElephant* thisfor non-constmember functions
In the code for print(), when we say name_, it's as if we wrote this->name_. And when we call print().
And, when we call a member function, it passes the address of the object we called it on. So when we write charlie.print(), it's as almost as if we wrote Elephant::print(&charlie), except that the ”this” argument is a secret hidden argument.
So basically, behind the scenes, the member function works almost exactly like the global function.
Yes.
But why isn't
thisa reference? That's the more C++-styleprintElephantfunction, not the one that takes a pointer.
I introduced
thisin 1979, I didn't introduce references until 1985. By that point there was more than five years of code wherethiswas a pointer. And it's not like you need to saythisvery often anyway.
And now we've had 37 more years of living with it as a pointer. Gah.
If you want the actual object a member function was called on, you need to say *this, because this is a pointer to the target object, not the object itself.
Sometimes when we look at student code, we see students wanting to write
this->age_or(*this).age_because they think it's more explicit. But it's not. It's just more typing.
The trailing underscore helps us remember that it's a member variable, so adding in
this->as well is just noise.
Okay, we've made some good progress and we're nearly done. Let's head back up to the parent page to check our progress and maybe take a break.
(When logged in, completion status appears here.)