Initializing variables in header C++
Solution 1
Aside from the obvious incorrect naming (which I assume was simply a matter of hastily creating an analogous example and is not the actual issue in your code), you need to declare the variable as extern
in your .h/.hpp file. You cannot have an extern
variable that is also static
since the (one of the) use(s) of static
is to keep the variable contained to within a single .cpp
file.
If you change:
static int testNumber = 10;
in your A.h
file to:
extern int testNumber;
and then in your A.cpp
file do something like:
#include "A.h"
int testNumber = 10;
Now go ahead and run:
int main() {
//changeNumber();
std::cout << testNumber << std::endl; // prints 10
changeTestNumber(); // changes to 15
std::cout << testNumber << std::endl; // prints 15
std::cin.ignore();
return 0;
}
Be sure to fix the function names!
Solution 2
Goodies and others are certainly correct, but let me put one more step ahead:
static
makes the definition local to the translation unit. So defining a static global variable in the header will result in as many copies as the translation units it is included. Unless that's not specifically what you want that's not the wayextern
tells the compiler that the global variable exist somewhere, but is not defined and must be searched at link phase. To the linker to succeed, you need to define it somewhere (typically a source file where it make more sense to exist)Omitting both of them will result in a "multiple definition" linker error, where more than one source includes an header.
Now, the 2nd case has two limitation:
- it forces you to have a compilable source to instantiate a global object even in the case you are providing a template library (or an "header only" library) making delivery more complex as required
- It exposes to the so called global initialization fiasco: if you initialize a global object with values taken from other global objects defined elsewhere, since C++ doesn't grant about their order of construction (that ultimately belongs to the way the linker works), you may have trouble in proper initialization and destruction of global objects.
To avoid all this, consider that
- A global defined function, if explicitly declared as
inline
can be linked more times and - Template functions as well as in-class defined member functions are in-lined by default
- static local object are created only once, the first time they are encountered
You can define global values in headers by making them static local to functions: like in
inline int& global_val() //note the &
{ static int z = 0; return z; }
the only drawback is that you have always to place a ()
upon every access.
Since the local value is unique and instantiated upon a call, this will ensure that, if there are dependencies between globals (think to int z=0
as int z=something_else()
) they will be created in the order they are needed and destroyed in reverse order, even in case of recursion and multiple threads (since c++14)
Considering the evolution of C++ towards generics and functional paradigms, and considering that placing all sources in a single compilation unit is sometime preferable than linking many sources... Have a think about not using global variables, but replacing them with inlined instatiator functions.
Editing about 2 years later:
C++17 have finally introduced the inline directive for also for variable declarations, just as a syntactic shortcut to the function expansion.
So -today- you can simply write
inline const float PI = 3.14159;
inline int goodies = 25;
Solution 3
A.h
extern int testNumber;
void changeNumber();
A.cpp
#include "A.h"
int testNumber = 10;
void changeTestNumber()
{
testNumber = 15;
}
B.h
#include "A.h"
// some other stuff
B.cpp
#include "B.h"
// some other stuff
main.cpp
#include "B.h"
#include <iostream>
int main(){
changeTestNumber();
std::cout<<testNumber<<std::endl;
return 0;
}
Please try like that.
Comments
-
remi almost 2 years
EDIT: correct function names, and added #pragma once
This is a very strong simplification of my problem, but if I do this:
A.h
#pragma once static int testNumber = 10; void changeTestNumber();
A.cpp
#pragma once #include "A.h" void changeTestNumber() { testNumber = 15; }
B.h
#pragma once #include "A.h" // some other stuff
B.cpp
#pragma once #include "B.h" // some other stuff
main.cpp
#pragma once #include "B.h" #include <iostream> int main(){ changeTestNumber(); std::cout<<testNumber<<std::endl; return 0; }
Why am I not getting testNumber = 15 at the call out? What really happens when I use a function that is included in a header of my included header? If I remove the static in from of int testNumber, I will get some error about my testNumber being initialized twice.
So is my header compiled twice when I do this?
Thanks in advance!