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* this
forconst
member functionsElephant* this
for non-const
member 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
this
a reference? That's the more C++-styleprintElephant
function, not the one that takes a pointer.I introduced
this
in 1979, I didn't introduce references until 1985. By that point there was more than five years of code wherethis
was a pointer. And it's not like you need to saythis
very 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.)