¿Por qué #define es malo y cuál es el sustituto adecuado?

#define dItemName L"CellPhone" 

Definirlo como una variable constante. Es una buena práctica de progtwigción.

 const wchar_t *dItemName = L"CellPhone"; 

En caso de que necesite saber la longitud de su cadena en algún lugar posterior, defínala como una matriz:

 const wchar_t dItemName[] = L"CellPhone"; 

Además, por qué #define es malo: transforma todos los lugares donde se usa la palabra dItemName en L “CellPhone”. Ejemplo:

 struct { int dItemName; } SomeStruct; 

se convertirá en inválido:

 struct { int L"CellPhone"; } SomeStruct; 

Curiosamente, no pude encontrar una sola pregunta que apuntara todas las desventajas, incluso el tema ciertamente se ha discutido antes.

Antes que nada, no es que en C (no en C ++) esta es la manera de declarar una constante. Esto también explica por qué tantos desarrolladores de C ++ todavía lo usan: cuando provienen del fondo C o han sido enseñados por personas aprendidas de personas con antecedentes C, tienden a reproducir este comportamiento C-ish.

En C ++, sin embargo, tenemos instalaciones superiores.

#define no define una constante, define una macro

  1. Una macro no conoce scope
  2. Una macro no es segura

Una macro no conoce el scope:

Son instalaciones de preprocesamiento: el preprocesador no tiene conocimiento de las reglas del lenguaje subyacente (ya sea asm, C o C ++) y siempre expandirá los símbolos que tiene en existencia sin tener en cuenta el scope.

Por esta razón, generalmente se recomienda utilizar un conjunto específico de símbolos para establecer macros aparte. La gente generalmente usa los símbolos ALL_CAPS , aunque debes recordar que:

  • no deben contener dos guiones bajos consecutivos
  • no deberían comenzar por un guión bajo

para cumplir con el estándar C ++.

Una macro no es segura.

Como dije, el preprocesador ignora las reglas de lenguaje subyacentes, por lo tanto, lo siguiente no le parece extraño:

 #define FOO "foo" int main(int argc, char* argv[]) { if (FOO) { ... } return 0; } 

Por otro lado, usar un tipo apropiado evitaría este error involuntario:

 std::string const Foo = "foo"; 

Conclusion?

Puedes usar un #define si lo deseas, solo estás haciendo el trabajo extra en lugar del comstackdor, pero esa es tu decisión. Personalmente: soy perezoso 🙂

Un problema importante con #define es que está fuera del lenguaje mismo y, por lo tanto, no está limitado a un ámbito determinado. Reemplazará dItemName en cualquier lugar de la unidad de traducción, en todos los espacios de nombres, clases, funciones, etc.

Lo reemplazaría con const std::wstring dItemName = L"CellPhone";

#define es una instrucción de preprocesador que define una macro. En su caso macro dItemName con el valor L"CellPhone" .

Las macros son malas principalmente porque se procesan antes de que el código sea real. Esto significa que no están sujetos a los ámbitos y a las reglas de la syntax de C ++. Si tienes una variable en algún lugar llamada dItemName , probablemente las cosas no funcionen: tendrás errores de comstackción difíciles de entender debido a eso.

La solución es declarar dItemName como una variable (en este caso una variable const ).

Debido a que las macros de preprocesador, que acaba de crear, contaminan todos los ámbitos de nombre. Están disponibles en todas partes y no siguen las reglas de scope de nomenclatura estándar. Por lo tanto, con una macro como esa, código como int dItemName = 5; en su lugar, el preprocesador lo ignora para, en cambio, ser int L"CellPhone" = 5; . Una variable global constante no haría esto.

Dejando a un lado todas las demás cuestiones, esta es la IMNSHO, el peor problema con las definiciones macro.

Apuntar a definir hacer aquello para lo que fueron inventados como un fracaso es … culpar a un cuchillo por cortar.

Si no nombra correctamente sus definiciones con UPPERCASE_NAMES, tendrá problemas, pero de todos modos tendrá esos problemas en C si no puede autodisciplinar su estilo de trabajo.

No se puede usar const para generar sistemas de reorganización dinámica, por lo que no es adecuado para cualquier aplicación incorporada que se personalice antes de la comstackción. El contenido solo se puede asignar a constantes de preevaluación, por lo que ni siquiera otras expresiones const.

El hecho de que una Herramienta no se doblega ante el OO-Paradigma no se vuelve inútil de repente. Const no es un reemplazo igual con respecto a la funcionalidad.