83

class C {
  T a;
public:
  C(T a): a(a) {;}
};

Is it legal?

yesraaj
  • 46,370
  • 69
  • 194
  • 251
Sergey Skoblikov
  • 5,811
  • 6
  • 40
  • 49

6 Answers6

70

Yes it is legal and works on all platforms. It will correctly initialize your member variable a, to the passed in value a.

It is considered by some more clean to name them differently though, but not all. I personally actually use it a lot :)

Initialization lists with the same variable name works because the syntax of an initialization item in an initialization list is as follows:

<member>(<value>)

You can verify what I wrote above by creating a simple program that does this: (It will not compile)

class  A
{

   A(int a)
   : a(5)//<--- try to initialize a non member variable to 5
   {
   }
};

You will get a compiling error something like: A does not have a field named 'a'.


On a side note:

One reason why you may not want to use the same member name as parameter name is that you would be more prone to the following:

class  A
{

   A(int myVarriable)
   : myVariable(myVariable)//<--- Bug, there was a typo in the parameter name, myVariable will never be initialized properly
   {
   }
   int myVariable;
};

On a side note(2):

One reason why you may want to use the same member name as parameter name is that you would be less prone to the following:

class  A
{

   A(int myVariable_)
   {
     //<-- do something with _myVariable, oops _myVariable wasn't initialized yet
     ...
     _myVariable = myVariable_;
   }
   int _myVariable;
};

This could also happen with large initialization lists and you use _myVariable before initializing it in the initialization list.

Brian R. Bondy
  • 339,232
  • 124
  • 596
  • 636
  • 3
    It's a matter of taste. I prefer to give identical names to identical thing. That's why I use namespaces widely. – Sergey Skoblikov Nov 06 '08 at 13:01
  • 2
    Very often for private fields you will find naming like "a_" or "_a". – Marcin Gil Nov 06 '08 at 13:06
  • Member variables are often m_a or _a. Scoped variables are often a_. – Brian R. Bondy Nov 06 '08 at 13:12
  • 1
    I've recently switched to using this technique too (and disambiguating with this-> in method bodies). It's my preferred way in C#, and coming back to C++ I've ditched my old practice of using the m_ prefix for member variables. Much nicer now (YMMV) – philsquared Nov 06 '08 at 13:28
  • about side note one: compiler will tell me about non-used parameter. – Sergey Skoblikov Nov 06 '08 at 15:20
  • sometimes in projects warnings get lost though because of the level of warning set or because of third party includes that you can't fix. – Brian R. Bondy Nov 06 '08 at 18:12
  • I always set maximum warning level. To deal with misbehaving third party headers one can use '#pragama warning' with 'suppress' option or 'disable' and 'default' options. It's for Visual C++. – Sergey Skoblikov Nov 06 '08 at 21:40
  • @BrianR.Bondy third party includes can be silenced by marking their path system, like for gcc `-isystem /some/path` instead of usual `-I/some/path`. – Ruslan Jan 10 '16 at 11:27
36

One of the things that may lead to confusion regarding this topic is how variables are prioritized by the compiler. For example, if one of the constructor arguments has the same name as a class member you could write the following in the initialization list:

MyClass(int a) : a(a)
{
}

But does the above code have the same effect as this?

MyClass(int a)
{
    a=a;
}

The answer is no. Whenever you type "a" inside the body of the constructor the compiler will first look for a local variable or constructor argument called "a", and only if it doesn't find one will it start looking for a class member called "a" (and if none is available it will then look for a global variable called "a", by the way). The result is that the above statment "a=a" will assign the value stored in argument "a" to argument "a" rendering it a useless statement.

In order to assign the value of the argument to the class member "a" you need to inform the compiler that you are referencing a value inside this class instance:

MyClass(int a)
{
    this->a=a;
}

Fine, but what if you did something like this (notice that there isn't an argument called "a"):

MyClass() : a(a)
{
}

Well, in that case the compiler would first look for an argument called "a" and when it discovered that there wasn't any it would assign the value of class member "a" to class member "a", which effectively would do nothing.

Lastly you should know that you can only assign values to class members in the initialization list so the following will produce an error:

MyClass(int x) : x(100) // error: the class doesn't have a member called "x"
{
}
Dragonion
  • 585
  • 1
  • 6
  • 10
9

if the formal parameter and the member is named same then beware of using this pointer inside constructor to use the member variable

class C {
  T a;
public:
  C(T a): a(a) {
this->a.sort ;//correct
a.sort();//will not affect the actual member variable
}
};
yesraaj
  • 46,370
  • 69
  • 194
  • 251
4

Legal: yes, as explained by Brian, compiler knows the name to expect in the initializer list must be a member (or a base class), not anything else.

Good style: most likely not - for a lot of programmers (including you, it seems) the result is not obvious. Using a different name for the parameter will keep the code legal and make it a good style at the same time.

I would prefer writing some of:

class C {
  T a_;
public:
  C(T a): a_(a) {}
};


class C {
 T a;
 public:
 C(T value): a(value) {}
};
Suma
  • 33,181
  • 16
  • 123
  • 191
  • 1
    No, for me result is obvious. if a(a) construct is legal then it definitely means that those 'a' are different. I just wasn't sure is it really legal in C++. – Sergey Skoblikov Nov 06 '08 at 13:42
  • 1
    You need to be very careful about using identifiers with leading underscores, to avoid clashes with the implementation. You're actually OK when it's followed by a lowercase char, as here, but it's widely considered best to avoid them altogether. See question 228783 for more. – tragomaskhalos Nov 06 '08 at 13:45
  • It is a matter of preference, there are benefits both ways. – Brian R. Bondy Nov 06 '08 at 14:05
  • 1
    @SergeySkoblikov it's not that obvious: `a=a` is also legal, but it doesn't mean LHS and RHS have different meaning. – Ruslan Jan 10 '16 at 11:30
2

The problem with this practice, legal though it may be, is that compilers will consider the variables shadowed when -Wshadow is used, and it will obfuscate those warnings in other code.

Moreover, in a non-trivial constructor, you make make a mistake, forgetting to put this-> in front of the member name.

Java doesn't even allow this. It's bad practice, and should be avoided.

Rick
  • 3,298
  • 3
  • 29
  • 47
2

Hey guys this is a great question. If you want to identical names for fields and constructor parameters / methods parameter you have to use scope resolution ( :: ) operator or you can use this ( this-> ) to map the parameter value with member like this please check the code snippet carefully you can understand easyly.

class Student{
    private :
        string name;
        int rollNumber;

    public:
        Student()
        {
           // default constructor
        }

        // parameterized constructor
        Student(string name, int rollNumber)
        {
            this->name = name;
            Student::rollNumber = rollNumber;
        }

        void display()
        {
            cout<<"Name: "<<name <<endl;
            cout<<"Roll Number: "<<rollNumber<<endl;
        }

        void setName(string name)
        {
            this->name = name;
        }

        void setrollNumber(int rollNumber)
        {
            Student::rollNumber = rollNumber;
        }

};