109

Is it possible to initialize a static const value outside of the constructor? Can it be initialized at the same place where member declarations are found?

class A {
private:
  static const int a = 4;
  /*...*/
};
jogojapan
  • 68,383
  • 11
  • 101
  • 131
anarhikos
  • 1,415
  • 3
  • 15
  • 19
  • 13
    Yes, what you have works (but only for integral types). – UncleBens Aug 20 '10 at 13:07
  • 5
    Just wanted to add that `static` has nothing to do with constructors since `static` members are not specific to a given instance and exist outside of it. – ereOn Aug 20 '10 at 13:10
  • In fact, you *must* initialize const statics outside a class constructor. Otherwise it wouldn't be a const static. DUCY? – John Dibling Aug 20 '10 at 14:10
  • Possible duplicate of [C++ where to initialize static const](http://stackoverflow.com/questions/2605520/c-where-to-initialize-static-const) – CharlesB Jan 11 '17 at 16:28

4 Answers4

120

YES you can but only for int types. If you want your static member to be any other type, you'll have to define it somewhere in a cpp file.

class A{
private:
 static const int a = 4; // valid
 static const std::string t ; // can't be initialized here
 ...
 ...
};


// in a cpp file where the static variable will exist 
const std::string A::t = "this way it works";

Also, note that this rule have been removed in C++11, now (with a compiler providing the feature) you can initialize what you want directly in the class member declaration.

Klaim
  • 67,274
  • 36
  • 133
  • 188
  • 2
    @anarhikos - the in-class initialization only works for integral types. `double` is not an integral type. – Brian Neal Aug 20 '10 at 13:31
  • 2
    @anrhikos: That's why you shouldn't define inside the class. You should define outside the class as a matter of practice (see my answer) –  Aug 20 '10 at 13:35
  • What if I don't want to assign a value? What if I just want the default constructor to run? I get errors about re-declaring the variable outside the class if I don't assign anything. – Ben Farmer Mar 09 '16 at 13:49
  • 4
    @anarhikos, you need inline before static const (C++17), or constexpr – Zhang Mar 25 '19 at 06:09
  • 4
    It would be great if this answer would be extended to what you would need to do in c++11 or c++17. Basically adding @Zhang's comment to the answers – C. Binair Mar 03 '21 at 15:19
40

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();
int C::n = Y::r;
int C::p = y.r;       // error
int C::q = y.f();     // error

The initializations of C::p and C::q cause errors because y is an object of a class that is derived privately from C, and its members are not accessible to members of C.

If a static data member is of const integral or const enumeration type, you may specify a constant initializer in the static data member's declaration. This constant initializer must be an integral constant expression. 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.

cyber
  • 103
  • 3
21

Just for the sake of completeness, I am adding about the static template member variables.

template<class T> struct X{
   static T x;
};

template<class T> T X<T>::x = T();

int main(){
   X<int> x;
}
Chubsdad
  • 24,777
  • 4
  • 73
  • 129
  • 2
    Thanks [@Chubsdad](https://stackoverflow.com/users/418110) for sharing! It was very hard to find the correct syntax. – Evandro Coan Nov 13 '18 at 00:32
7

You cannot initialize static members within constructors. Integral types you can initialize inline at their declaration. Other static members must be defined (in a .cpp) file:

// .h
class A{
private:
 static const int a = 4;
 static const foo bar;
 ...
 ...
};

// .cpp
const foo A::bar = ...;
sbi
  • 219,715
  • 46
  • 258
  • 445