问题
I'm trying to access the static variable in other header file from a CPP file.
"Boo.hpp
"
#ifndef Boo_hpp
#define Boo_hpp
static int num;
class Boo
{
public:
Boo()
{
num = 35;
}
};
#endif /* Boo_hpp */
"Foo.hpp
"
#ifndef Foo_hpp
#define Foo_hpp
class Foo
{
public:
Foo();
};
#endif /* Foo_hpp */
"Foo.cpp
"
#include "Foo.hpp"
#include "Boo.hpp"
#include <iostream>
Foo::Foo()
{
std::cout << "Num : " << num << '\n';
}
"main.cpp
"
#include <iostream>
#include "Foo.hpp"
#include "Boo.hpp"
int main()
{
Boo boo;
Foo foo;
}
The Result I get :
Num : 0
Program ended with exit code: 0
The Result I expect :
Num : 35
Program ended with exit code: 0
If I move the class Foo
's constructor implementation from Foo.cpp
to Foo.hpp
, my code works as expected.
However, I would like to be able to access the num
from Foo.cpp
.
How should I fix my code?
回答1:
You need to understand two things to understand what is happening here.
In C++, header files are just text which is "copy-pasted" to each .cpp file which includes them, directly or indirectly. The resulting preprosessed source code is "compilation unit", so you can basically think one .cpp file is one compilation unit.
static
global variables (not to be confused with static member variables of classes, AKA class variables, which are essentially same as non-static global variables...) are visible inside the compilation unit they are defined in. If you define static global variable in two compilation units, they are completely independent variables, and do not interfere (their names are not visible outside the compilation unit either). So, unless you know you do want separate copy of the variable in multiple .cpp files (very rare), you shouldn't put static global variables in .h file (extern
declaration of global variable defined in a .cpp file is what you usually want in a .h file).
Now when you combine these two things, you realize that the static variable defined in .h file is no different from static variable defined in .cpp file. If .h file is included in several .cpp files, you get several copies of the variable, and which one is being used depends on which .cpp file it is (directly or through includes).
You have two .cpp files, which both define same static variable here, so they have two copies, and code compiled in these will use different variables.
Now there is extra quirk here. If you define a member function, including the constructor, inline (happens implicitly when you define it inside a class, if you define it in .h file but outside class you have to use the inline
keyword), then every .cpp file will get a different copy of that function. Now you as programmer promise they will be the same, that is what inline
means (it has only a little to do with inline optimization). If you have several copies of the same constructor (defined in a .h file), and they actually access different static variable, then they are not the same, and you break the promise. Don't do that!
回答2:
All translation units which includes the Boo.hpp
will have their own definition of the num
variable. No other TU (Translation Unit) will have the same num
variable.
That's what the static
linkage storage modifier means (for non-local, non-member variables).
回答3:
The keyword static
on globals in C/C++ instructs the compiler to limit that symbol to the current compilation unit, i.e. the file it's declared in. Putting static
declarations into header files is a huge trap because even though you include the same header in all your source files, each file will receive its own copy of the static symbol.
What you want is the extern
keyword, that declares the symbol to be shared between compilation units, i.e. extern int num
.
Some more reading on storage class specifiers here
来源:https://stackoverflow.com/questions/52025196/access-static-variable-from-cpp-file-to-other-header-file