Static data members (C++ only)

The declaration of a static data member in the member list of a class is not a definition. You must define the static member outside of the class declaration, in namespace scope. For example:
class X
{
public:
      static int i;
};
int X::i = 0; // definition outside class declaration

Once you define a static data member, it exists even though no objects of the static data member's class exist. In the above example, no objects of class X exist even though the static data member X::i has been defined.

Static data members of a class in namespace scope have external linkage. The initializer for a static data member is in the scope of the class declaring the member.

A static data member can be of any type except for void or void qualified with const or volatile. You cannot declare a static data member as mutable.

You can only have one definition of a static member in a program. Unnamed classes, classes contained within unnamed classes, and local classes cannot have static data members.

Static data members and their initializers can access other static private and protected members of their class. The following example shows how you can initialize static members using other static members, even though these members are private:
class C {
      static int i;
      static int j;
      static int k;
      static int l;
      static int m;
      static int n;
      static int p;
      static int q;
      static int r;
      static int s;
      static int f() { return 0; }
      int a;
public:
      C() { a = 0; }
      };
C c;
int C::i = C::f();    // initialize with static member function
int C::j = C::i;      // initialize with another static data member
int C::k = c.f();     // initialize with member function from an object
int C::l = c.j;       // initialize with data member from an object
int C::s = c.a;       // initialize with nonstatic data member
int C::r = 1;         // initialize with a constant value
class Y : private C {} y;

int C::m = Y::f();    // error
int C::n = Y::r;      // error
int C::p = y.r;       // error
int C::q = y.f();     // error
The initialization of C::m, C::n, C::p, and C::q causes errors because the values used to initialize them are private members of class Y which can not be accessed.

If a static data member is of a const integral or const enumeration type, you can specify a constant initializer in the static data member's declaration. This constant initializer must be an integral constant expression.

C++11A static data member of a literal type can be declared with the constexpr specifier in the class definition, and the data member declaration must specify a constant initializer. For example:
struct Constants { 
  static constexpr int bounds[] = { 42, 56 };
};

float a[Constants::bounds[0]][Constants::bounds[1]];
C++11
Note that the constant initializer is not a definition. You still need to define the static member in an enclosing namespace. The following example demonstrates this:
#include <iostream>
using namespace std;

struct X {
  static const int a = 76;
};

const int X::a;

int main() {
  cout << X::a << endl;
}
The tokens = 76 at the end of the declaration of static data member a is a constant initializer.