2008-11-06 27 views

Respuesta

39

Sí, es legal y funciona en todas las plataformas. Inicializará correctamente su variable miembro a, al valor pasado a.

Se considera por algunos más limpio para nombrarlos de manera diferente, aunque no todos. Yo personalmente realidad lo uso mucho :)

listas de inicialización con el mismo nombre de variable funciona porque la sintaxis de un elemento de inicialización en una lista de inicialización es el siguiente:

< miembro de > (<valor>)

puede verificar lo que he escrito anteriormente mediante la creación de un sencillo programa que hace esto: (no se compilará)

class A 
{ 

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

Usted recibirá una error de compilación algo así como: A no tiene un campo llamado 'a'.


En una nota:

Una de las razones por las que posible que no desea a utilizar el mismo nombre de usuario 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 (2):

una de las razones por qué y ou puede querer a utilizar el mismo nombre de usuario 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 grandes listas de inicialización y utilizar _myVariable antes de inicializar en la inicialización lista.

+2

Es una cuestión de gusto. Prefiero dar nombres idénticos a algo idéntico. Es por eso que uso espacios de nombres ampliamente. –

+1

Muy a menudo, para los campos privados encontrará nombres como "a_" o "_a". –

+0

Las variables miembro a menudo son m_a o _a. Las variables de ámbito son a menudo a_. –

4

Legal: sí, según 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 (incluyéndote a ti, parece) 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.

yo preferiría escribir algunos de:

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


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

No, para mí el resultado es obvio. si un (a) constructo es legal, entonces definitivamente significa que esos 'a' son diferentes.Simplemente no estaba seguro de que sea realmente legal en C++. –

+1

Debe tener mucho cuidado con el uso de identificadores con guiones bajos principales, para evitar conflictos con la implementación. En realidad, está bien cuando está seguido de un carácter en minúscula, como aquí, pero se considera que es mejor evitarlos por completo. Ver la pregunta 228783 para más. – tragomaskhalos

+0

Es una cuestión de preferencia, hay beneficios en ambos sentidos. –

7

si el parámetro formal y el miembro es nombrado misma, entonces tenga cuidado con el uso de este puntero dentro constructor para utilizar 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 
} 
}; 
+0

Hmm ... parece una excelente razón para nombrarlos de manera diferente. Buen punto. –

+0

Esta es una buena razón para usar 'const' para parámetros de entrada por valor invariables en implementaciones de funciones. – Ruslan

16

Uno de Lo 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 de constructor tiene el mismo nombre que un miembro de la clase se podría escribir lo siguiente en la lista de inicialización:

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

pero lo hace el código anterior tiene el mismo efecto que esto?

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.

Con el fin de asignar el valor del argumento a la miembro de la clase "A" debe informar al compilador que se hace referencia a un valor dentro de este caso clase:

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

bien, pero lo si se hizo algo como esto (nótese que no hay un argumento llamado "a"):

MyClass() : a(a) 
{ 
} 

Bueno, en ese caso, el compilador buscará primero un argumento llamado "a" y cuando se descubrió que no había ninguno lo haría Señale el valor del miembro de la clase "a" al miembro de la clase "a", lo que efectivamente no haría nada.

Finalmente usted debe saber que sólo puede asignar valores a los miembros de la clase en la lista de inicialización de modo que el siguiente producirá un error:

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

El problema con esta práctica, legal, aunque puede ser, 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.

Cuestiones relacionadas