2010-01-29 15 views
5

¿Este código es ambiguo o está perfectamente bien (aprobado por estándares/tiene un comportamiento consistente para cualquier compilador que exista)?¿Es ambiguo o está perfectamente bien?

struct SCustomData { 
    int nCode; 
    int nSum; 
    int nIndex; 
    SCustomData(int nCode, int nSum, int nIndex) 
     : nCode(nCode) 
     , nSum(nSum) 
     , nIndex(nIndex) 
    {} 
}; 

edición:
sí, me refiero al hecho de que las variables miembro tienen el mismo nombre con parámetros formales del constructor.

+3

Seré honesto, tuve que leerlo dos veces ... Probablemente sería un desarrollador desdichado si tuviera que seguir leyendo el mismo código dos veces. –

+3

Lo sentimos, pero ¿qué se supone que es ambiguo al respecto? Me parece sencillo. –

+0

Lo que es ambiguo (para los humanos) es tener el mismo identificador para un atributo y un parámetro ... –

Respuesta

6

No, en este caso hay ninguna ambigüedad, pero consideran siguiente:

struct SCustomData { 
//... 
    void SetCode(int nCode) 
    { 
      //OOPS!!! Here we do nothing! 
      //nCode = nCode; 

      //This works but still error prone 
      this->nCode = nCode; 
    } 
}; 

Usted debe llamar la atención sobre uno de los estilos de codificación existentes. Por ejemplo, General Naming Rule in Google C++ Coding Styles o lea el excelente libro "C++ Coding Standards: 101 Rules, Guidelines, and Best Practices" de Herb Sutter y Andrei Alexandrescu.

+0

Regla simple que uso todo el tiempo: primera letra mayúscula para los parámetros, minúsculas para campos privados. –

+0

Prefiero el estilo de Sutter: camel Case - para parámetros (código - en este ejemplo), camel Case y guión bajo (_) - para campos privados (code_ - en este ejemplo). –

4

Su ejemplo no es ambiguo (para mí), pero no es una buena práctica, porque puede volverse tan ambiguo como el infierno.

Ha pasado mucho tiempo desde que escribí C++ enfadado, así que supongo que lo siguiente será suficiente.
¿Usted CONOCE ¿qué hará? ¿Estás seguro?

class Noddy 
{ 
    int* i; 
    Noddy(int *i) 
    : i(i) 
    { 
     if(i == NULL) 
      i = new int; 
    } 
}; 
+1

Sí, sé lo que hará, pero yo no apostaría dinero que mis colegas lo hacen :) –

+0

Dime Dime Dime! ¿El 'yo' interno se está refiriendo al 'más cercano declarado': el argumento? (La lista de inicializadores obviamente solo puede referirse al miembro) – xtofl

+2

@xtofl: Correcto, para hacer lo que "parece" como debería ser, tendría que ser "this-> i" dentro de las llaves {} –

1

Si se refiere a usar el mismo nombre para miembros y argumentos de constructor, entonces eso está absolutamente bien. Sin embargo, es posible que encuentre algunas personas que insisten en que es una mala práctica por alguna razón.

Si necesita acceder a los miembros en el cuerpo del constructor, entonces tienes que tener cuidado - ya sea dar los argumentos diferentes nombres, o utilizar this-> acceder a los miembros.

Si se refiere al uso de verrugas pseudohúngaras para recordarle a la gente que los números enteros son enteros, entonces eso está técnicamente permitido, pero no tiene absolutamente ningún beneficio y hace que el código sea mucho más difícil de leer. Por favor no lo hagas

+1

Como una de "esas personas", mis razones son a) el OP tuvo que preguntar sobre esto, por lo que probablemente otros lean ese código yb) vea su segundo párrafo. –

+1

@Neil: (a) no es posible escribir C++ de forma tal que las personas que lo leen no necesiten conocer C++, (b) Estoy completamente de acuerdo, en una función con un cuerpo no vacío, ocultando variables de miembros con parámetros es pedir problemas. La diferencia es que en (b), es fácil confundir accidentalmente a los dos, incluso si conoce bien el lenguaje, simplemente porque se olvidó de la ocultación de un minuto al siguiente. Esto da como resultado errores. En (a), solo hay una intención plausible del código y la pregunta es si usted es consciente de que es legal. Esto resulta en un momento educativo. –

1

En general, he prefijado variables de instancia con guiones bajos y parámetros nombrados en el constructor sin ningún prefijo. Por lo menos, esto eliminará la ambigüedad de tus parámetros de tus variables de instancia. También hace la vida menos agitada si se inicializa dentro del cuerpo del constructor.

struct SCustomData { 
    int _nCode; 
    int _nSum; 
    int _nIndex; 
    SCustomData(int nCode, int nSum, int nIndex) 
     : _nCode(nCode), _nSum(nSum), _nIndex(nIndex) 
    {} 
}; 

// Alternatively 
struct SCustomData { 
    int _nCode; 
    SCustomData(int nCode) 
    { 
     this->_nCode = nCode; 
    } 
}; 

No me gusta apilar las variables tal como estaba escrito en la pregunta. Me gusta ahorrar espacio vertical, y también es más fácil para mí leer de izquierda a derecha. (Esta es una preferencia personal mío, no es una regla obligatoria ni nada de eso.)

+4

Desafortunadamente, los nombres de los identificadores que comienzan con el guión bajo están reservados tanto en C como en C++. – aib

0

es perfectamente conforme al estándar, pero hay son compiladores por ahí que no aceptaría variables miembro que tiene el mismo nombre que parámetros del constructor . De hecho, tuve que cambiar mi biblioteca de código abierto por ese motivo. Ver this patch

1

Yo diría que esto está perfectamente bien.

Es mi estilo preferido para los constructores que usan la lista de inicialización y no tienen ningún código. Creo que reduce la confusión porque es obvio qué parámetro constructor va a cada miembro.