C++ accessing variables from .CPP files
I'm a little fuzzy on how variable access between .cpp files works. For instance:
main.cpp
in开发者_开发百科t main()
{
int a = i;
return 0;
}
main2.cpp
int i;
This generates a compiler error on main.cpp, telling me there is no in i in existence. What difference then, does the "static" keyword do in this context? (I tried Googling for it, but most of the "static keyword" info pages talk about classes & functions)
main2.cpp
static int i;
Is it the same? Does it prevent extern int i
being used to access i
elsewhere? How does the use of anonymous namespaces differ in how variables are handled?
main2.cpp
namespace
{
int i;
}
To sum up:
- Can variables be accessed between .cpp files? (aside from extern keyword)
- How does the static keyword on a global variable affect things?
- How do anonymous namespaces affect things differently?
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.
All global variables have some kind of linkage. extern
linkage is required to name the same variable in different contexts between different files.
extern
is the default. If you actually use extern
in a variable declaration, it's treated as a reference to another file. Omit any linkage specifier to actually create the variable; this must happen in only one file.
extern int i; // i exists somewhere in some .cpp file.
int i; // ah! this is the file it exists in.
// (Although nothing special about that.)
static
applied to a global (at namespace scope) makes it local to the file. You get the same effect from a private namespace, so static
outside function or class scope is deprecated. Many still use it though.
The exception to the rule of static
meaning file-local is in classes and inline
functions. Class static
members should more properly be called extern
since the semantics are identical. It's ugly and confusing, but I guess Bjarne just wanted to eliminate extern
as a keyword.
Inline functions can have the same definition among multiple .cpp
files, so when one creates a static
variable, the variable definition is shared as well.
- yes, for example you can use static class variables
- it makes variable local and persistent to compilation unit
- anonymous namespace prevents collision between symbols. it is as if you create uniquely named namespace manually
精彩评论