c++ - tipos - ¿Puedo usar nombres idénticos para los campos y los parámetros del constructor?
que es un constructor en programacion (5)
Sí, es legal y funciona en todas las plataformas. Inicializará correctamente su variable miembro a, al valor pasado a.
Sin embargo, es considerado por algunos más limpio nombrarlos de manera diferente, pero no todos. Personalmente, realmente lo uso mucho :)
Las listas de inicialización con el mismo nombre de variable funcionan porque la sintaxis de un elemento de inicialización en una lista de inicialización es la siguiente:
<miembro> (<valor>)
Puede verificar lo que escribí arriba creando un programa simple que hace esto: (No compilará)
class A
{
A(int a)
: a(5)//<--- try to initialize a non member variable to 5
{
}
};
Obtendrá un error de compilación algo así como: A no tiene un campo llamado ''a''.
En otros comentarios:
Una de las razones por las que es posible que no desee utilizar el mismo nombre de miembro como nombre de parámetro es que sería más propenso a lo siguiente:
class A
{
A(int myVarriable)
: myVariable(myVariable)//<--- Bug, there was a typo in the parameter name, myVariable will never be initialized properly
{
}
int myVariable;
};
En una nota lateral (2):
Una de las razones por las que puede querer usar el mismo nombre de miembro como nombre de parámetro es que sería menos propenso a lo siguiente:
class A
{
A(int myVariable_)
{
//<-- do something with _myVariable, oops _myVariable wasn''t initialized yet
...
_myVariable = myVariable_;
}
int _myVariable;
};
Esto también podría ocurrir con listas de inicialización grandes y usa _myVariable antes de inicializarlo en la lista de inicialización.
class C {
T a;
public:
C(T a): a(a) {;}
};
¿Es legal?
Legal: sí, según lo explica Brian, el compilador sabe que el nombre esperado en la lista de inicializadores debe ser un miembro (o una clase base), nada más.
Buen estilo: lo más probable es que no; para muchos programadores (incluido usted, parece que) el resultado no es obvio. Usar un nombre diferente para el parámetro mantendrá el código legal y lo convertirá en un buen estilo al mismo tiempo.
Preferiría escribir algo de:
class C {
T a_;
public:
C(T a): a_(a) {}
};
class C {
T a;
public:
C(T value): a(value) {}
};
si el parámetro formal y el miembro reciben el mismo nombre, tenga cuidado con el uso de este puntero dentro del constructor para usar la variable miembro
class C {
T a;
public:
C(T a): a(a) {
this->a.sort ;//correct
a.sort();//will not affect the actual member variable
}
};
Una de las cosas que puede generar confusión con respecto a este tema es cómo el compilador prioriza las variables. Por ejemplo, si uno de los argumentos del constructor tiene el mismo nombre que un miembro de la clase, puede escribir lo siguiente en la lista de inicialización:
MyClass(int a) : a(a)
{
}
Pero, ¿tiene el código anterior el mismo efecto que este?
MyClass(int a)
{
a=a;
}
La respuesta es no. Cada vez que escriba "a" dentro del cuerpo del constructor, el compilador primero buscará una variable local o argumento constructor llamado "a", y solo si no encuentra uno, comenzará a buscar un miembro de la clase llamado "a" (y si ninguno está disponible, entonces buscará una variable global llamada "a", por cierto). El resultado es que el enunciado anterior "a = a" asignará el valor almacenado en el argumento "a" al argumento "a" convirtiéndolo en una afirmación inútil.
Para asignar el valor del argumento al miembro de la clase "a", debe informar al compilador que está haciendo referencia a un valor dentro de esta instancia de clase:
MyClass(int a)
{
this->a=a;
}
Bien, pero ¿y si hicieras algo como esto? (Fíjate que no hay un argumento llamado "a"):
MyClass() : a(a)
{
}
Bueno, en ese caso el compilador primero buscaría un argumento llamado "a" y cuando descubriera que no había ninguno asignaría el valor del miembro de la clase "a" al miembro de la clase "a", lo que efectivamente no haría nada .
Por último, debe saber que solo puede asignar valores a los miembros de la clase en la lista de inicialización, por lo que lo siguiente producirá un error:
MyClass(int x) : x(100) // error: the class doesn''t have a member called "x"
{
}
El problema con esta práctica, aunque legal, es que los compiladores considerarán las variables sombreadas cuando se use -Wshadow, y ofuscarán esas advertencias en otro código.
Además, en un constructor no trivial, comete un error, olvidándose de poner esto-> delante del nombre del miembro.
Java ni siquiera permite esto. Es una mala práctica, y debe evitarse.