Defining static members in C++

I am trying to define a public static variable like this :

public :
         static int j=0;        //or any other value too

I am getting a compilation error on this very line : ISO C++ forbids in-class initialization of non-const static member `j'.

  1. Why is it not allowed in C++ ?

  2. Why are const members allowed to be initialized ?

  3. Does this mean static variables in C++ are not initialized with 0 as in C?

Thanks !


Solution 1:

(1.) Why is it not allowed in C++ ?

From Bjarne Stroustrup's C++ Style and Technique FAQ:

A class is typically declared in a header file and a header file is typically included into many translation units. However, to avoid complicated linker rules, C++ requires that every object has a unique definition. That rule would be broken if C++ allowed in-class definition of entities that needed to be stored in memory as objects.

(2.) Why are const members allowed to be initialized ?

[dirkgently said it better]

(3.) Does this mean static variables in C++ are not initialized with 0 as in C?

As far as I know, as long as you declare the static member var in a .cpp it will be zero-initialized if you don't specify otherwise:

// in some .cpp
int Test::j; // j = int();

Solution 2:

You will have to initialize the static variable in a .cpp file and not in the class declaration.

When you declare a static variable in the class, it can used without instantiating a class.

//Header file
class Test
{
  public:
    static int j;
};

//In cpp file

//Initialize static variables here.
int Test::j = 0;

//Constructor
Test::Test(void)
{
   //Class initialize code
}

Solution 3:

Why is it not allowed in C++ ?

Until and unless you define it, the variable doesn't become a l-value.

Why are const members allowed to be initialized ?

Even in this case, a definition is required if you are going to take the address of the variable.

9.4.2 Static data members

2 The declaration of a static data member in its class definition is not a definition and may be of an incomplete type other than cv-qualified void. The definition for a static data member shall appear in a namespace scope enclosing the member’s class definition. In the definition at namespace scope, the name of the static data member shall be qualified by its class name using the :: operator. The initializer expression in the definition of a static data member is in the scope of its class

Also, this is primarily an usage artifact so that you can write:

class S {
      static const int size = 42;
      float array[ size ];
};

Does this mean static variables in C++ are not initialized with 0 as in C?

No they are:

3.6.2 Initialization of non-local variables

Variables with static storage duration (3.7.1) or thread storage duration (3.7.2) shall be zeroinitialized (8.5) before any other initialization takes place.

Though things get a bit more trickier in C++0x. All literal types can now be initialized (as opposed to only integral types in the current standard) which would mean that all scalar types (floats included) and some class types can now be initialized using an initializer in the declaration.

Solution 4:

The short answer:

It's equivalent to saying extern int Test_j = 0;.

If it did compile, what would happen? Every source file that includes your class's header file would define a symbol called Test::j initialized to 0. The linker tends not to like that.