Reputation: 361
What is the proper way of accessing a member data/function that is part of the method's class? There appears to be 3 means:
class test{
private:
int variable;
public:
void setVariable(int value) {
variable = value; // method 1, using the variable name directly
this->variable = value; // method 2, via pointer dereference of 'this'
test::variable = value; // method 3, via scope operator
}
};
They all seems to work as far as I can tell. Are they equivalent? Is there a reason to use one over the other beside style/consistency?
Upvotes: 3
Views: 125
Reputation: 7249
As a side note: When using method 1 if there is a naming conflict with the function parameter and member variable the function parameter will be used over the member variable.
if we have:
void setVariable(int variable) {
variable = variable; // method 1, this does not change the member variable.
this->variable = variable; // method 2, via pointer dereference of 'this'
test::variable = variable; // method 3, via scope operator
}
Upvotes: 1
Reputation: 926
And to add to the above answers:
Some code styles like to identify member variables using a fixed prefix like _
or m
. Using "method 2" is another (and imho much nicer way) of achieving this clarity in the code.
Prefering this->value
over value
is also a little like using std::cin
instead cin
with a using namespace std
.
Upvotes: 0
Reputation: 208353
In general it does not matter so the simpler options member = value;
is preferred. In some cases there might be ambiguity with a local variable and there you can qualify with the this->
prefix, but a better approach would be avoid the ambiguity altogether.
There are however some corner cases where it does matter. When dealing with virtual functions, using a qualified name (type::member
) disables runtime dispatch and ensures that the final overrider at the type
level is called:
struct base {
virtual int f() { return 1; }
};
struct derived : base {
virtual int f() { return 2; }
void g() {
std::cout << f() << "\n";
std::cout << derived::f() << "\n";
}
};
struct mostderived : derived {
virtual int f() { return 3; }
};
int main() {
mostderived d;
d.g(); // 3 2
}
When dealing with template classes and inheritance, lookup is performed in two phases. During the first phase, non-dependent names have to be resolved. An unqualified name is a non-dependent name, so in some cases you need to qualify with either this->
or type::
, and the distinction above still applies. The extra qualification serves to make the name dependent:
template <typename T>
struct derived : T {
void g() {
// std::cout << f() << "\n"; // Error, cannot resolve f() [*]
this->f(); // Ok, pick final overrider at runtime
derived::f(); // Ok, pick overrider here: base::f()
}
};
struct base {
virtual int f() { return 1; }
};
struct mostderived : derived<base> {
virtual int f() { return 3; }
};
int main() {
mostderived d;
d.g(); // 3, 1
}
Upvotes: 3
Reputation: 7439
There is no difference in performance. The ::
is used to avoid ambiguities, such as when you have a local variable with same name of a field, or a base class that declares a field with same name of a field in a derived class. The ->
is supported because the type of this
is a pointer to object, so the compiler must accept this->something
, and that can also be used to avoid ambiguities or just to let code more clear.
Upvotes: 0
Reputation: 490148
For code inside the object, it generally makes no difference, so it's usually cleanest to just use variable = value;
and be done with it.
Sometimes in a template, you can run into a situation where just using the variable name by itself is ambiguous, and this->variable
removes that ambiguity -- but this is rare enough that I definitely would not use this->everything
on a regular basis just because it might be useful once in a great while.
Upvotes: 1
Reputation: 20074
The pointer this is often used for comparison in an overloaded operator of a class. One of its uses can be if the parameter passed in the function is the same as the object itself, for example:
class CDummy {
public:
int isitme (CDummy& param);
};
int CDummy::isitme (CDummy& param)
{
if (¶m == this) return true;
else return false;
}
This is also used to return a pointer to the object itself
ClassEx ClassEx::Func(//params)
{
//code
return *this;
}
As for normal comparison, value
instead of this->value
will be more efficient to use, the use of this->
is ambiguous unless you're checking values.
Upvotes: 0
Reputation: 22089
In addition to style and consistency, as you mention, sometimes you have to use a specific syntax to disambiguate.
"method 2" can be used to disambiguate between local variables and class members.
"method 3" can be used to disambiguate between fields with the same name in different places of your class hierarchy.
Upvotes: 3
Reputation: 60007
Use method 1
variable = value;
Saves you buying a new keyboard so frequently!
(Having said that I should stop stilling coffee over mine!)
Upvotes: -1