sirve que para namespace dev create c++ namespaces global-namespace

que - ¿Por qué incluir "usar el espacio de nombres" en un archivo de encabezado es una mala idea en C++?



namespace c++ para que sirve (4)

Bueno, ¿cuál es el sentido de usar espacios de nombres? Es para evitar el riesgo de colisiones de nombres.

Digamos que tiene un nombre de clase bastante común, por ejemplo, FooBar. Si utiliza varias bibliotecas, existe el riesgo de que FooBar en la biblioteca A colisione con FooBar en la biblioteca B. Para eso usamos dos espacios de nombres diferentes A y B, para mover los FooBars del espacio de nombres global a A :: FooBar y B :: FooBar (por lo que se mantienen separados el uno del otro).

Si luego pones using A; y using B; en los encabezados, esto moverá A :: FooBar y B :: FooBar a solo FooBar, provocando la colisión, eliminando la ganancia de usar espacios de nombres en primer lugar.

Mientras leía "Thinking in C ++" de Bruce Eckel sobre los espacios de nombres, me encontré con la siguiente afirmación:

Sin embargo, prácticamente nunca verá una directiva de uso en un archivo de encabezado (al menos no fuera del alcance). La razón es que el uso de directiva elimina la protección de ese espacio de nombre particular, y el efecto dura hasta el final de la unidad de compilación actual. Si coloca una directiva using (fuera de un ámbito) en un archivo de encabezado, significa que esta pérdida de "protección de espacio de nombre" ocurrirá dentro de cualquier archivo que incluya este encabezado, lo que a menudo significa otros archivos de encabezado.

¿Podría ayudarme a comprender la declaración anterior con algún ejemplo fácil?


Considera este programa:

line# 1 #include <string> 2 3 using namespace std; 4 5 struct string { const char* p; }; // Beware: another string! 6 7 int main() 8 { 9 string x; // Error: ambiguous - which string is wanted? 10 }

Si intenta compilarlo, verá errores:

g++ using.cc -o using using.cc: In function `int main()'': using.cc:9: error: use of `string'' is ambiguous using.cc:5: error: first declared as `struct string'' here /usr/lib/gcc/i386-redhat-linux/3.4.6/../../../../include/c++/3.4.6/bits/stringfwd.h:60: error: also declared as `typedef struct std::basic_string<char, std::char_traits<char>, std::allocator<char> > std::string'' here using.cc:9: error: `string'' was not declared in this scope using.cc:9: error: expected `;'' before "x"

El problema aquí es que cuando main() especifica la string x; , el compilador no está seguro de si se desea la ::string definida por el usuario o std::string incluida.

Ahora imagine que toma la parte superior del programa ... líneas 1 a 5 - hasta e incluyendo la struct string ... y póngalo en un archivo de encabezado que luego #include before main() . Nada cambia: todavía tienes un error. Por lo tanto, al igual que para los programas independientes, los archivos de encabezado con instrucciones using en ellos pueden causar problemas para otros códigos que los incluyen, lo que hace que algunas de sus declaraciones sean ambiguas.

Sin embargo, puede ser un dolor más grande, ya que los encabezados se pueden incluir, directa o indirectamente, arbitrariamente en grandes cantidades de código dependiente, y ...

  • eliminar la instrucción de uso del encabezado, o
  • un cambio en el contenido de <string> , o cualquier otro encabezado que afecte a std::

... podría romper código incluyendo el encabezado problemático. Cualquiera de los dos problemas puede hacer que el código dependiente no se pueda compilar, y es posible que los problemas no se noten hasta que se intente otra compilación. Además, la persona que sufre debido a la declaración de using puede no tener permisos de sistema de archivos / repositorio de código, autoridad corporativa, etc. para eliminar la instrucción de uso del encabezado, ni corregir otro código de cliente afectado.

Dicho esto, si un encabezado solo tiene "uso" dentro de una clase o función, entonces no hay efecto en el código más allá de ese alcance, por lo que el impacto potencial de los cambios en std :: se reduce drásticamente.


Copie el siguiente párrafo de "C ++ Primer, fifth edition":

El código dentro de los encabezados normalmente no debe usar el using declaraciones. La razón es que los contenidos de un encabezado se copian en el texto del programa incluido. Si un encabezado tiene una declaración de uso, entonces cada programa que incluye ese encabezado obtiene esa misma declaración de uso. Como resultado, un programa que no intenta utilizar el nombre de biblioteca especificado puede encontrar conflictos de nombres inesperados.


Si un encabezado contiene el using namespace std , todo el espacio de nombres se agrega al espacio de nombres global en cada módulo que incluye el encabezado.

Esto significa que nunca puede declarar una función o definir una clase con el mismo nombre (y parámetros compatibles para una función) como una función / clase std en el espacio de nombres global en cualquiera de esos módulos.