In your first example, main2.cpp
defines a global variable i
, which could have been accessed by main.cpp
if an extern
declaration of i
had appeared in that file. (Normally that extern declaration would come from a header file.) You got a compiler error because i
had never been declared in main.cpp
, which means the compiler assumes there is no such variable.
In your second example, main2.cpp
defines a file scope variable i
. File scope variables are distinct from globals, even if they happen to have the same name. If you had had an extern declaration of i
in main.cpp
in the second example, both files would have compiled successfully, but then you would have gotten a link error because no global variable i
was defined.
If you renamed main2.cpp
from the second example to main3.cpp
, added an extern declaration of i
to main.cpp
, compiled all three and linked them all together, that would succeed; main.cpp and main2.cpp would share one variable named i
, and main3.cpp
would have its own entirely separate variable also named i
.
This stuff is called linkage. Namespaces are almost entirely unrelated to linkage. However, the anonymous namespace is special. Defining a variable in an anonymous namespace is for all practical purposes the same as defining it with static
-- it makes it a file scope variable. (If I remember correctly, there is a difference, but it only matters if you are doing complicated things with exported templates, and as exported templates are so little used that they're talking about deleting the feature from the C++ standard, you don't have to worry about it.)
The value of the anonymous namespace is that you can put a class definition inside it, and that makes all of the class's methods be file-local. (Only the class { ... }
block has to be inside the namespace { ... }
block to get this effect.) You can't do that any other way.