First, your question itself. In the first example, you use...
std::cout << ::p;
That prepended ::
resolves namespaces in a specific order, starting with the local namespace. (See this answer). Thus, it looks for p
globally, locally, and then in an external namespace (X
). Because it found p
locally, it stops looking.
In the second example, you are explicitly resolving your namespace:
std::cout << X::p;
Thus, there's no search order to be bothered with. It is just going to look for p
in the namespace X
, and fail otherwise.
This leads to the second problem: you appear to be confusing the purpose of the using namespace
keywords. Those are intended to enable you to use a more shorthand approach of resolving to a namespace, instead of always using the fully qualified name (x::p
).
However, the computer will still look in the local namespace first, and THEN the using
namespaces in the order they are found. As always, once the computer finds the thing named in a namespace, it stops looking.
This leads to a major principle in C++: don't use using namespace
! There are exceptions, but you'll pick up on those as you work. The issue comes down to ambiguity as to what namespace something will be coming from, which is exactly the problem you described.
For example, imagine you define the namespaces X
and Y
in separate classes, and then you simply have the following...
#include "x.hpp"
#include "y.hpp"
using namespace x;
using namespace y;
int main()
{
std::cout << p << std::endl;
}
Where'd p
come from? Looking at x.hpp
and y.
hpp, you see that BOTH have
p, so which one is used? And then, what if you add
using namespace z;above them? Now you have to check if
zhas
p`. ARGH!
(See this answer for more information on namespace resolution.)
It is important to note that, as far as the compiler/linker are concerned, there is no ambiguity. It has an implicit resolution order to handle that. The ambiguity is all on the coder.
Even worse, what if you define q
locally, without realizing that x
or y
have a q
as well? What will it resolve to?
This is a situation you never want to create! Borrowing from Tim Peter's Zen of Python (albeit, different language, but some of the principles therein are true in most languages)...
Explicit is better than implicit.
So, how can we write this to be less wibbly-wobbly timey-wimey?
Drop using namespace
. The only time you should even touch this is if you are using a bunch of stuff from one namespace, and virtually nothing from anywhere else. (You'll notice most C++ programmers won't even do using namespace std;
)
Use the fully qualified name on anything you use sparingly-to-moderately. For example, x::p
.
If you use something a lot, use the command using x::p
at the top of the file. This resolves p
to namespace x
, without confusing everything else.
In short, you should be able to tell, at a glance, what namespace everything comes from. Never create a situation of ambiguity and implicit resolution; only bugs and pain lie that way.