What is the best way to initialize a private, static data member in C++? I tried this in my header file, but it gives me weird linker errors:
class foo
{
Does this serves your purpose?
//header file
struct MyStruct {
public:
const std::unordered_map<std::string, uint32_t> str_to_int{
{ "a", 1 },
{ "b", 2 },
...
{ "z", 26 }
};
const std::unordered_map<int , std::string> int_to_str{
{ 1, "a" },
{ 2, "b" },
...
{ 26, "z" }
};
std::string some_string = "justanotherstring";
uint32_t some_int = 42;
static MyStruct & Singleton() {
static MyStruct instance;
return instance;
}
private:
MyStruct() {};
};
//Usage in cpp file
int main(){
std::cout<<MyStruct::Singleton().some_string<<std::endl;
std::cout<<MyStruct::Singleton().some_int<<std::endl;
return 0;
}
What about a set_default()
method?
class foo
{
public:
static void set_default(int);
private:
static int i;
};
void foo::set_default(int x) {
i = x;
}
We would only have to use the set_default(int x)
method and our static
variable would be initialized.
This would not be in disagreement with the rest of the comments, actually it follows the same principle of initializing the variable in a global scope, but by using this method we make it explicit (and easy to see-understand) instead of having the definition of the variable hanging there.
For future viewers of this question, I want to point out that you should avoid what monkey0506 is suggesting.
Header files are for declarations.
Header files get compiled once for every .cpp
file that directly or indirectly #includes
them, and code outside of any function is run at program initialization, before main()
.
By putting: foo::i = VALUE;
into the header, foo:i
will be assigned the value VALUE
(whatever that is) for every .cpp
file, and these assignments will happen in an indeterminate order (determined by the linker) before main()
is run.
What if we #define VALUE
to be a different number in one of our .cpp
files? It will compile fine and we will have no way of knowing which one wins until we run the program.
Never put executed code into a header for the same reason that you never #include
a .cpp
file.
include guards (which I agree you should always use) protect you from something different: the same header being indirectly #include
d multiple times while compiling a single .cpp
file
The linker problem you encountered is probably caused by:
This is a common problem for those who starts with C++. Static class member must be initialized in single translation unit i.e. in single source file.
Unfortunately, the static class member must be initialized outside of the class body. This complicates writing header-only code, and, therefore, I am using quite different approach. You can provide your static object through static or non-static class function for example:
class Foo
{
// int& getObjectInstance() const {
static int& getObjectInstance() {
static int object;
return object;
}
void func() {
int &object = getValueInstance();
object += 5;
}
};
I just wanted to mention something a little strange to me when I first encountered this.
I needed to initialize a private static data member in a template class.
in the .h or .hpp, it looks something like this to initialize a static data member of a template class:
template<typename T>
Type ClassName<T>::dataMemberName = initialValue;
The class declaration should be in the header file (Or in the source file if not shared).
File: foo.h
class foo
{
private:
static int i;
};
But the initialization should be in source file.
File: foo.cpp
int foo::i = 0;
If the initialization is in the header file then each file that includes the header file will have a definition of the static member. Thus during the link phase you will get linker errors as the code to initialize the variable will be defined in multiple source files.
The initialisation of the static int i
must be done outside of any function.
Note: Matt Curtis: points out that C++ allows the simplification of the above if the static member variable is of const int type (e.g. int
, bool
, char
). You can then declare and initialize the member variable directly inside the class declaration in the header file:
class foo
{
private:
static int const i = 42;
};