Possible Duplicate:
Members vs method arguments access in C++
I have a class that has some members, like x
, y
, width
and height
. In its constructor, I wouldn't do this:
A::A(int x, int y, int width, int height)
{
x = x;
y = y;
width = width;
height = height;
}
This doesn't really make sense and when compiled with g++ x
, y
, width
, and height
become weird values (e.g. -1405737648
).
What is the optimal way of solving these naming conflicts?
You can use initialization lists just fine with the same names:
An alternative is to use different names, if you don't want to have the same names. Some Hungarian-notation variation comes to mind (I might get some hate for this):
But there's nothing wrong with the first suggestion.
If you must use assignments in the constructor (as opposed to using a list of initializers, which is preferred) the specific pattern to address this issue is to use
this
pointer, as follows:You can just change the names of the constructor arguments. When you write
then you're assigning the arguments of the constructor to themselves, leaving the actual instance variables uninitialized, that's why you're getting bogus values.
The general solution I suggest (and widely use) is to change the names of the arguments of the constructor method:
If at all possible, it's better to set data members via the initializer list, in which case there's no problem with arguments that shadow member names. Another alternative is to use
this->foo = foo;
in the body of the constructor. A similar problem exists for setters, but now you can't use the initializer list solution. You're stuck withthis->foo = foo;
-- or just use different names for arguments and members.Some people really hate arguments that shadow data members; multiple coding standards explicitly say never to do this. Others think this kind of shadowing, at least for constructors and setters, is the cat's meow. I recall reading one or two coding standards (but I don't recall which) that designated this kind of shadowing as a "should" (but not "shall") practice.
One final option is to use shadowing in the function declaration so as to give readers a hint as to what the function does, but use distinct names in the implementation.
Update: What is "shadowing"?
The innermost declaration of
i
,int i=10
, shadows the variablei
declared in thefor
statement, which in turn shadows the variablei
declared at function scope, which in turn shadows the global variablei
.In the problem at hand, the arguments
x
,y
,width
, andheight
to the non-default constructor for classA
shadow the member data with the same names as those arguments.Your
width=width;
did nothing because the argumentwidth
shadows (hides) the data memberwidth
. When you have two or more variables with the same name that were declared at different scopes, the winner is always the name with the innermost scope. In general, it is always the name with the innermost scope that wins.Although you can avoid the problem by using the constructor's initialization list, I suggest following a convention for naming data members, for instance, a trailing
_
, or a leadingm_
. Otherwise you are very likely to have name clashes, specially if you have members with names such asx
andy
.