When should I explicitly write this->member
in a method of
a class?
The main (or I can say, the only) purpose of this
pointer is that it points to the object used to invoke a member function.
Base on this purpose, we can have some cases that only using this
pointer can solve the problem.
For example, we have to return the invoking object in a member function with argument is an same class object:
class human {
...
human & human::compare(human & h){
if (condition)
return h; // argument object
else
return *this; // invoking object
}
};
Although I usually don't particular like it, I've seen others use this-> simply to get help from intellisense!
If you declare a local variable in a method with the same name as an existing member, you will have to use this->var to access the class member instead of the local variable.
#include <iostream>
using namespace std;
class A
{
public:
int a;
void f() {
a = 4;
int a = 5;
cout << a << endl;
cout << this->a << endl;
}
};
int main()
{
A a;
a.f();
}
prints:
5
4
Usually, you do not have to, this->
is implied.
Sometimes, there is a name ambiguity, where it can be used to disambiguate class members and local variables. However, here is a completely different case where this->
is explicitly required.
Consider the following code:
template<class T>
struct A {
int i;
};
template<class T>
struct B : A<T> {
int foo() {
return this->i;
}
};
int main() {
B<int> b;
b.foo();
}
If you omit this->
, the compiler does not know how to treat i
, since it may or may not exist in all instantiations of A
. In order to tell it that i
is indeed a member of A<T>
, for any T
, the this->
prefix is required.
Note: it is possible to still omit this->
prefix by using:
template<class T>
struct B : A<T> {
using A<T>::i; // explicitly refer to a variable in the base class
int foo() {
return i; // i is now known to exist
}
};
The other uses for this (as I thought when I read the summary and half the question... .), disregarding (bad) naming disambiguation in other answers, are if you want to cast the current object, bind it in a function object or use it with a pointer-to-member.
void Foo::bar() {
misc_nonconst_stuff();
const Foo* const_this = this;
const_this->bar(); // calls const version
dynamic_cast<Bar*>(this)->bar(); // calls specific virtual function in case of multi-inheritance
}
void Foo::bar() const {}
void Foo::baz() {
for_each(m_stuff.begin(), m_stuff.end(), bind(&Foo:framboozle, this, _1));
for_each(m_stuff.begin(), m_stuff.end(), [this](StuffUnit& s) { framboozle(s); });
}
void Foo::framboozle(StuffUnit& su) {}
std::vector<StuffUnit> m_stuff;
void Foo::boz() {
bez(&Foo::bar);
bez(&Foo::baz);
}
void Foo::bez(void (Foo::*func_ptr)()) {
for (int i=0; i<3; ++i) {
(this->*func_ptr)();
}
}
Hope it helps to show other uses of this than just this->member.
There are few cases where using this
must be used, and there are others where using the this
pointer is one way to solve a problem.
1) Alternatives Available: To resolve ambiguity between local variables and class members, as illustrated by @ASk.
2) No Alternative: To return a pointer or reference to this
from a member function. This is frequently done (and should be done) when overloading operator+
, operator-
, operator=
, etc:
class Foo
{
Foo& operator=(const Foo& rhs)
{
return * this;
}
};
Doing this permits an idiom known as "method chaining", where you perform several operations on an object in one line of code. Such as:
Student st;
st.SetAge (21).SetGender (male).SetClass ("C++ 101");
Some consider this consise, others consider it an abomination. Count me in the latter group.
3) No Alternative: To resolve names in dependant types. This comes up when using templates, as in this example:
#include <iostream>
template <typename Val>
class ValHolder
{
private:
Val mVal;
public:
ValHolder (const Val& val)
:
mVal (val)
{
}
Val& GetVal() { return mVal; }
};
template <typename Val>
class ValProcessor
:
public ValHolder <Val>
{
public:
ValProcessor (const Val& val)
:
ValHolder <Val> (val)
{
}
Val ComputeValue()
{
// int ret = 2 * GetVal(); // ERROR: No member 'GetVal'
int ret = 4 * this->GetVal(); // OK -- this tells compiler to examine dependant type (ValHolder)
return ret;
}
};
int main()
{
ValProcessor <int> proc (42);
const int val = proc.ComputeValue();
std::cout << val << "\n";
}
4) Alternatives Available: As a part of coding style, to document which variables are member variables as opposed to local variables. I prefer a different naming scheme where member varibales can never have the same name as locals. Currently I'm using mName
for members and name
for locals.