Reputation: 567
I mean, we can't do:
class A {
int i;
char c;
public:
A(int i = 0, char c = ' ') : this->i(i), this->c(c) {}
};
Is it because the instance hasn't been created yet or something like that?
Upvotes: 2
Views: 208
Reputation: 10998
It is because the this
pointer needs to be inside one of the following:
It can appear in the following contexts:
1) Within the body of any non-static member function, including member initializer list
2) within the declaration of a non-static member function anywhere after the (optional) cv-qualifier sequence, including dynamic exception specification(deprecated), noexcept specification(C++11), and the trailing return type(since C++11)
3) within brace-or-equal initializer of a non-static data member (since C++11)
class Foo {
int a[sizeof(*this)]; // error, not inside a member function
};
Similarly:
class A {
int i = sizeof(*this); // valid - brace-or-equal initializer
char c;
public:
// Error, not inside member function.
A(int i = 0, char c = ' ') : this->i(i), this->c(c) // invalid
{}
};
When put inside of the body of the constructor, it will work:
A(int i = 0, char c = ' ')
{
this->c = c; // 'this->' required for disambiguation
this->i = i;
}
A(int i = 0, char c = ' ') : i(sizeof(*this)) // also valid
{}
It is often not necessary to use this->
explicitly.
Upvotes: 0
Reputation: 48615
You don't need to use this
like that:
class A {
int i;
char c;
public:
A(int i = 0, char c = ' ') : i(i), c(c) {} // syntax makes this good
};
That is totally fine and works exactly how you want it to work.
The syntax rules mean that parameters can not appear as the variable being initialized, only its parameter. So the compiler must resolve the variables outside the parens i()
as the class member and the one inside the parens (i)
from the parameters because they hide the member variables due to scoping rules.
A(int i = 0): i(i) {}
^ - syntax says that i must be a member
A(int i = 0): i(i) {}
^ - syntax says normal scoping rules apply
Outside the parens it must be a class member but inside the parens the scoping rules are like in the constructor body - the parameters hide the member variables.
So it is a perfectly safe pattern to use to name your parameters the same as your data members.
Upvotes: 0
Reputation: 3342
You don't need the this
keyword in the initializer list as anything in the initializer list must be declared within the class. When you do
class MyClass
{
int member;
public:
MyClass(int member) : member(member) { }
^^^^^ Can only be resolved to a member of MyClass
}
member
in the initializer list is not permitted to refer to anything other than int member
within the class. Therefore the this keyword is unnecessary and would add additional parsing difficulties if compilers had to support both member(member)
and this->member(member)
within initializer list. While giving the impression that it is possible to initialize non-member variables within the initializer list at the same time.
Upvotes: 2
Reputation: 8529
If you look at an overview of the C++ grammar, specifically the mem-initializer-list
section, you see that the initializer list should consist of identifier(expression)
or classname(expression)
entries. An identifier
is defined here as string of digits and nondigits (a-z, A-Z, _).
Your this->identifier(expression)
doesn't match that, so it's not allowed. It's not necessary anyway, because there is no ambiguity here. The identifier
is always a member variable of the class, so it's clear which i
is referred to.
class A {
int i;
char c;
public:
A(int i = 0, char c = ' ') : i(i), c(c) {}
};
Upvotes: 1