2010-03-19 23 views
11

Siempre he sido un buen chico al escribir mis clases, anteponiendo todas las variables miembro con m_:C++ Constructor lista de inicialización extrañeza

class Test { 
    int m_int1; 
    int m_int2; 
public: 
    Test(int int1, int int2) : m_int1(int1), m_int2(int2) {} 
}; 

int main() { 
    Test t(10, 20); // Just an example 
} 

Sin embargo, hace poco se olvidó de hacer eso y terminó escribiendo:

class Test { 
    int int1; 
    int int2; 
public: 
    // Very questionable, but of course I meant to assign ::int1 to this->int1! 
    Test(int int1, int int2) : int1(int1), int2(int2) {} 
}; 

Lo creas o no, el código compilado sin errores/advertencias y las asignaciones se realizaron correctamente! Fue solo cuando estaba haciendo el control final antes de verificar mi código cuando me di cuenta de lo que había hecho.

Mi pregunta es: ¿por qué mi código compila? ¿Se permite algo así en el estándar C++, o es simplemente un caso en el que el compilador es inteligente? En caso de que se lo pregunte, estaba usando Visual Studio 2008

+4

Mangling sus nombres es difícilmente lo que consideraría ser un "buen chico". Como ya sabrá, generalmente no es necesario, y en las raras ocasiones en que lo hace, tenemos el prefijo 'this->'. – jalf

+0

Quizás un idiota, vea http://stackoverflow.com/questions/2227244/what-if-a-constructor-parameter-has-the-same-name-as-a-member-variable-in-c – Abhay

+2

@jalf : Por otro lado, algún tipo de indicador de miembros-var a veces puede hacer que sea más fácil leer el código (utilizo el último _ cuando no se rompe la convención existente). –

Respuesta

26

Sí, es válido. Los nombres en la lista de inicializadores de miembros se buscan en el contexto de la clase del constructor para que int1 encuentre el nombre de la variable miembro.

La expresión del inicializador se busca en el contexto del propio constructor para que int1 encuentre el parámetro que enmascara las variables miembro.

+2

Exactamente a la derecha, y de forma concisa. ¡Bravo! +1 –

+0

+1, ¡buen chico! xD –

0

Imagino que esto funciona porque estaba usando int1 en la lista de inicializadores, y las únicas cosas que puede inicializar son variables miembro => de hecho no fue ambigua qué variable era siendo inicializado

Si todos los compiladores de C++ serían tan indulgentes, es otro asunto.

+0

IIRC g ++ también autoriza eso :-). – p4bl0

+11

Es C++ estándar. –

+1

Gracias por la explicación. Por supuesto, solo las variables miembro pueden aparecer fuera de los paréntesis en la lista de inicialización. Pero lo que está dentro del paréntesis no está perfectamente claro. Por ejemplo, si tenemos: Test (int int1): int1 (int1 + 1), int2 (int1) {} ahora, ¿qué significa int1 en los segundos paréntesis?¿Significa :: int1 o significa esto-> int1? – Andy

15

Lo que ha hecho es estándar C++. Solo las variables miembro o las clases base pueden iniciarse en la lista de inicialización, por lo que la variable fuera de la paranthesis no es ambigua. Dentro del paréntesis, se aplican las reglas de ámbito típico, y los nombres se eclipsan por los nombres de los parámetros.

+1

+1 Esta es la única respuesta que dice catagráficamente que es C++ estándar, además de dar una explicación. –

2

Este es un comportamiento perfectamente normal. Como AAT correctamente señaló, no hay ambigüedad. Las variables inicializadas por la lista deben ser miembros de la clase. Esto es estándar y funciona en todos los compiladores compatibles.

Lo único que debe recordar al usar una lista como esta es que una persona que no entiende este tipo de código puede tener que mantenerla. No hay nada de malo en escribir un código de inicialización como este siempre que sepa lo que está haciendo.

0

Lo que ha hecho es normal. Este tipo de implementación le evita incluso el uso del puntero "this" (en este caso).

Cuestiones relacionadas