studio programacion para móviles español edición desarrollo desarrollar curso aprende aplicaciones c++ scope namespaces forward-declaration using-directives

c++ - programacion - ¿Qué hace exactamente el uso de "espacio de nombres"?



manual programacion android español pdf (3)

Aquí hay una declaración de test de variable en el espacio de nombres X

04: namespace X 05: { 06: extern std::string test; 07: };

No es una definición de la variable. La variable también debe definirse antes de poder utilizarla para obtener su valor.

Podría hacer esta declaración también una definición si inicializa la variable. Por ejemplo

04: namespace X 05: { 06: extern std::string test = "Test"; 07: };

En este caso el código se compilaría con éxito.

En esta declaración

14: std::cout << X::test << std::endl;

hay un acceso al nombre calificado X::test . El compilador busca este nombre en el espacio de nombres X como se especifica en la variable y encuentra la declaración. Ahora necesita obtener el valor de la variable pero no puede encontrar su definición.

En esta declaración

10: std::string test = "Test";

existe una test variable declarada y definida en el espacio de nombres global porque se declara fuera de cualquier espacio de nombres explícitamente especificado.

Usted podría escribir

10: std::string X::test = "Test"; ^^^^^^^

en lugar de

10: std::string test = "Test";

Si desea definir la variable declarada en el espacio de nombres X

En cuanto a la directiva de uso, introduce los nombres declarados en el espacio de nombres especificado en el espacio de nombres donde se usa la directiva.

Por ejemplo, si escribir usando una test nombre no calificado

14: std::cout << test << std::endl; ^^^^^

entonces habrá una ambigüedad porque este nombre puede referirse al nombre X::test y ::test debido a la directiva de uso.

El siguiente código de prueba de C ++ no se vincula (gcc 4.9.2, binutils 2.25). El error está In function ''main'': undefined reference to ''X::test'' .

01: #include <string> 02: #include <iostream> 03: 04: namespace X 05: { 06: extern std::string test; 07: }; 08: 09: using namespace X; 10: std::string test = "Test"; 11: 12: int main() 13: { 14: std::cout << X::test << std::endl; 15: }

Debido a la línea 09, esperaba que la línea 10 definiera la variable X::test declarada en la línea 06. Creo que, en cambio, una variable de test no relacionada se declara y define en el espacio de nombres global, de ahí el error de enlace.

Pregunta: ¿Podría alguien explicar por qué mi expectativa era incorrecta y qué está sucediendo exactamente?

No es la respuesta:

  • Puedo hacer que enlace la línea 10 cambiante a std::string X::test = "Test"; .
  • No debería usar "usar espacio de nombres" para empezar.

La directiva que using namespace X; hace que los nombres del espacio de nombres X visibles dentro del espacio de nombres que contiene la directiva. Es decir, al buscar un nombre n en ese ámbito, se puede encontrar X::n . Sin embargo, solo se buscará si el compilador necesita buscarlo.

En su ejemplo, esta declaración:

std::string test = "Test";

Dentro del espacio de nombres global tiene perfecto sentido como está. La test nombre se introduce simplemente, como con cualquier otra declaración. No hay necesidad de buscarlo en ningún lado.

Este sería un hervidor de pescado completamente diferente:

namespace X { struct C { static std::string test; }; } using namespace X; std::string C::test = "Test";

En este código, el compilador necesita saber qué es C para dar sentido a la definición de C::test . Por lo tanto, realiza una búsqueda de nombres de C , que de hecho encuentra X::C gracias a la directiva using .


using namespace significa que usa definiciones del espacio de nombres que especificó, pero eso no significa que todo lo que defina se está definiendo en un espacio de nombres que usa.

La lógica de este comportamiento es bastante simple. Digamos que tenemos el siguiente ejemplo:

namespace X { extern string test; }; namespace Y { extern string test; }; using namespace X; using namespace Y; string test = "value";

Siguiendo la lógica de ejemplo, el compilador simplemente no sabría en qué espacio de nombres debería definir la test , por lo que tendría que declarar explícitamente el espacio de nombres. En una vida real se define en un espacio de nombres global .

En su caso específico, define la variable de test fuera del espacio de nombres X donde se declara como extern . El enlazador busca la definición de X::test pero no encuentra y, como resultado, ve este error.