What does “using namespace” do exactly?

╄→гoц情女王★ 提交于 2021-02-16 05:48:05

问题


The following C++ test code does not link (gcc 4.9.2, binutils 2.25). The error is 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: }

Because of line 09, I was expecting line 10 to define the X::test variable declared on line 06. I believe that instead an unrelated test variable is declared and defined in the global namespace, hence the linking error.

Question: Could anyone please explain why my expectation was incorrect, and what is happening exactly?

Not the answer:

  • I can make it link changing line 10 to std::string X::test = "Test";.
  • I should not use "using namespace" to begin with.

回答1:


The directive using namespace X; makes names from namespace X visible inside the namespace containing the directive. That is, when looking up a name n in that scope, X::n can be found. However, it will only be looked for if the compiler needs to look for it.

In your example, this declaration:

std::string test = "Test";

inside the global namespace makes perfect sense as-is. The name test is simply introduced, as with any other declaration. No need to look it up anywhere.

This would be an entirely different kettle of fish:

namespace X
{
  struct C
  {
    static std::string test;
  };
}

using namespace X;
std::string C::test = "Test";

In this code, the compiler needs to know what C is to make sense of the definition of C::test. It therefore does a name lookup of C, which indeed finds X::C thanks to the using directive.




回答2:


using namespace means you use definitions from the namespace you specified, but it doesn't mean that everything that you define is being defined in a namespace you use.

Logic of this behavior is pretty simple. Let's say we have the following example:

namespace X
{
    extern string test;
};

namespace Y
{
    extern string test;
};

using namespace X;
using namespace Y;

string test = "value";

Following your example logic, compiler just would not know in which namespace it should define test, so you would have to declare the namespace explicitly. In a real life it is defined in a global namespace.

In your specific case you define the test variable outside of the X namespace where it is declared as extern. Linker looks for definition of the X::test but doesn't find and as a result you see this error.




回答3:


Here is a declaration of variable test in namespace X.

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

It is not a definition of the variable. The variable must be also defined before it can be used to get its value.

You could make this declaration also a definition if you initialize the variable. For example

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

In this case the code would compile successfully.

In this statement

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

there is an access to the qualified name X::test. The compiler searches this name in namespace X as it is specified in the variable and finds the declaration. Now it needs to get the value of the variable but it is unable to find its definition.

In this statement

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

there is declared and defined variable test in the global namespace because it is declared outside any explicitly specified namespace.

You could write

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

instead of

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

if you want to define the variable declared in the namespace X.

As for the using directive then it introduces names declared in the specified namespace in the namespace where the directive is used.

For example If to write using unqualified name test

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

then there will be an ambiguity because this name can refer to name X::test and ::test due to the using directive.



来源:https://stackoverflow.com/questions/34129141/what-does-using-namespace-do-exactly

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!