Puis-je utiliser des noms identiques pour les champs et les parameters du constructeur?

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

Est-ce légal?

Oui c’est légal et ça marche sur toutes les plateformes. Il initialisera correctement votre variable membre a, à la valeur passée a.

Il est considéré par certains plus propres de les nommer différemment, mais pas tous. Personnellement, je l’utilise beaucoup 🙂

Les listes d’initialisation avec le même nom de variable fonctionnent car la syntaxe d’un élément d’initialisation dans une liste d’initialisation est la suivante:

()

Vous pouvez vérifier ce que j’ai écrit ci-dessus en créant un programme simple qui fait ceci: (il ne comstackra pas)

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

Vous obtiendrez une erreur de compilation quelque chose comme: A n'a pas de champ nommé 'a'.


Sur une note de côté:

Une des raisons pour lesquelles vous ne souhaitez peut-être pas utiliser le même nom de membre que le nom du paramètre est que vous êtes plus enclin à ce qui suit:

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

Sur une note latérale (2):

Une des raisons pour lesquelles vous pouvez vouloir utiliser le même nom de membre que le nom du paramètre est que vous êtes moins enclin à ce qui suit:

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

Cela peut également se produire avec de grandes listes d'initialisation et vous utilisez _myVariable avant de l'initialiser dans la liste d'initialisation.

Une des choses qui peut entraîner une confusion concernant ce sujet est la manière dont les variables sont classées par le compilateur. Par exemple, si l’un des arguments du constructeur porte le même nom qu’un membre de la classe, vous pouvez écrire ce qui suit dans la liste d’initialisation:

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

Mais le code ci-dessus a-t-il le même effet?

 MyClass(int a) { a=a; } 

La réponse est non. Chaque fois que vous tapez “a” dans le corps du constructeur, le compilateur cherchera d’abord une variable locale ou un argument de constructeur appelé “a”, et seulement s’il n’en trouve pas, il commencera à rechercher un membre de classe appelé “a” (et si aucun n’est disponible, il recherchera alors une variable globale appelée “a”). Le résultat est que la déclaration ci-dessus “a = a” affectera la valeur stockée dans l’argument “a” à l’argument “a”, ce qui en fera une déclaration inutile.

Pour atsortingbuer la valeur de l’argument au membre de classe “a”, vous devez informer le compilateur que vous faites référence à une valeur dans cette instance de classe:

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

Bien, mais si vous faisiez quelque chose comme ça (remarquez qu’il n’y a pas d’argument appelé “a”):

 MyClass() : a(a) { } 

Eh bien, dans ce cas, le compilateur chercherait d’abord un argument appelé “a” et lorsqu’il découvrirait qu’il n’y en avait pas, il atsortingbuerait la valeur du membre de classe “a” au membre de classe “a”, ce qui ne ferait rien. .

Enfin, sachez que vous ne pouvez affecter des valeurs aux membres de la classe que dans la liste d’initialisation, ce qui produira une erreur:

 MyClass(int x) : x(100) // error: the class doesn't have a member called "x" { } 

si le paramètre formel et le membre sont nommés de la même manière, méfiez-vous de l’utilisation de ce pointeur à l’intérieur du constructeur pour utiliser la variable membre

 class C { T a; public: C(T a): a(a) { this->a.sort ;//correct a.sort();//will not affect the actual member variable } }; 

Juridique: oui, comme l’explique Brian, le compilateur sait que le nom à attendre dans la liste d’initialisation doit être un membre (ou une classe de base), et rien d’autre.

Bon style: probablement pas – pour beaucoup de programmeurs (y compris vous, semble-t-il), le résultat n’est pas évident. Utiliser un nom différent pour le paramètre gardera le code légal et en fera un bon style en même temps.

Je préférerais écrire quelques unes des:

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

Le problème avec cette pratique, si juridique soit-il, est que les compilateurs considéreront les variables occultées lorsque -Wshadow est utilisé, et cela masquera ces avertissements dans d’autres codes.

De plus, dans un constructeur non sortingvial, vous faites une erreur, en oubliant de mettre ceci-> devant le nom du membre.

Java ne le permet même pas. C’est une mauvaise pratique et devrait être évitée.