简体   繁体   中英

Accessing a global and namespace variable

I am trying to access variable x using using directive in the following code:

#include <iostream>
using namespace std;
int x = 10;
namespace e {
int x = 5;
}
int main() {
using namespace e; // Because of this line compiler shows error
cout << x;
return 0;
}

In general we use the following line to access x but I am getting error We can also use using e::x; But my question is why can't we use using namespace e;

In this example it may seem that using namespace e; makes names from namespace e available in main function scope. However it does not do this. Instead it tries to inject names (during unqulified lookup in main ) from namespace e into the nearest enclosing namespace of main and namespace e , to the global namespace that is. Therefore x becomes ambiguous.

Let's start with another example.

const int x = 10;

namespace e {
const int y = 5;
}

int main()
{
std::cout << e::y;
using namespace e;
std::cout << y;
}

There is variable with value 10 and name x in global namespace (which can be referred to as x simply) and variable with value 5 with name y in namespace e (which must be referred to as e::y ).

By adding using namespace e; , you inject all names from namespace e into global namespace. This means global namespace now contains names x and y , and namespace e contains name y . You can now refer to variable with value 5 using both y and e::y .

Now, back to your example. If we change y to x :

const int x = 10;

namespace e {
const int x = 5;
}

int main()
{
std::cout << e::x;
using namespace e;
std::cout << x;
}

There is x in global namespace and x in namespace e . By adding using namespace e; you inject all the names from namespace e to global namespace, so now global namespace contains names x and x , and namespace e contains name x . See the problem? Global namespace contains two names x , which confuses the compiler. When you try to print variable under the name x , compiler looks up names in global namespace and finds two x . It cannot choose which one you meant, so it throws error.

This is the main reason why using namespace (particularly using namespace std; ) is considered evil . One can easily break working code by updating a library or introducing a new function. Compiler error is best outcome in such a case, but sometimes it's possible that compiler will silently replace one function by another, because it matches better.

You can still access both variables using fully qualified names :

int main()
{
using namespace e;
std::cout << ::x << " "; //x from global with fully quafilied name
std::cout << ::e::x << " "; //x from namespace e with fully qualified name
std::cout << e::x; //not fully qualified, but not ambiguous either - only one x in namespace e
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM