views:

8636

answers:

5

This feels like a dumb question, but what is the best way to initialize a private, static data member in C++? I tried this but it gives me weird linker errors:

class foo
{
    private:
        static int i;
};

int foo::i = 0;

I'm guessing this is because I can't initialize a private member from outside the class. So what's the best way to do this?

+26  A: 

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.

Note: Matt Curtis: points out that C++ allows the simplification of the above if the static member variable is const POD (Plain Old Data) then you can declare and initialize in the header file.

class foo
{
    private:
        static int const i = 42;
};
Martin York
The class declaration can be anywhere
1800 INFORMATION
Yes. But I am assuming the question has been simplified. Technically the declaration and definition can all be in a single source file. But that then limits the use of class by other classes.
Martin York
I forgot to say that I put them in the same file. This worked like a charm. Thanks!
Jason Baker
actually not just POD, it has to be an int type as well (int, short, bool, char...)
Matt Curtis
Note that this isn't just a question of how the value is initialized: const integral types defined like this may be turned into compile time constants by the implementation. This isn't always what you want, since it ups the binary dependency: client code needs recompilation if the value changes.
Steve Jessop
Although since this one's private, I guess that's not a concern here. Sorry.
Steve Jessop
it must be integral and always a constant expression (never a function)
Gollum
Alf P. Steinbach
A: 

That is the correct way to initialize a static class member, and I tried your exact code and it seemed to build just fine. Maybe you have another issue?

1800 INFORMATION
+9  A: 

For a variable:

foo.h:

class foo
{
private:
    static int i;
};

foo.cpp:

int foo::i = 0;

This is because there can only be one instance of foo::i in your program. It's sort of the equivalent of extern int i in a header file and int i in a source file.

For a constant you can put the value straight in the class declaration:

class foo
{
private:
    static int i;
    const static int a = 42;
};
Matt Curtis
This is a valid point. I will add this too my explanation. But it should be noted this only works for POD types.
Martin York
+3  A: 
int foo::i = 0;

Is the correct syntax for initializing the variable, but it must go in the source file (.cpp) rather than in the header.

Because it is a static variable the compiler needs to create only one copy of it. You have to have a line "int foo:i" some where in your code to tell the compiler where to put it otherwise you get a link error. If that is in a header you will get a copy in every file that includes the header, so get multiply defined symbol errors from the linker.

David Dibben
+3  A: 

With a Microsoft compiler, static variables that are not int-like can also be defined in a header file, but outside of the class declaration, using the Microsoft specific __declspec(selectany).

class A
{
    static B b;
}

__declspec(selectany) A::b;

Note that I'm not saying this is good, I just say it can be done.

Johann Gerell