如何在C++中初始化“static const”数据成员?

110
可以在构造函数之外初始化静态常量数据成员吗?它可以在声明数据成员的地方进行初始化吗?
class A {
private:
  static const int a = 4;
  /*...*/
};

13
没问题,你的方法可行(但仅适用于整数类型)。 - UncleBens
5
只是想补充一点,static 与构造函数无关,因为 static 成员不针对特定实例,而是存在于其外部。 - ereOn
事实上,您必须在类构造函数之外初始化const静态变量。否则它将不会是一个const静态变量。明白吗? - John Dibling
可能是C++中静态常量初始化的位置的重复问题。 - CharlesB
4个回答

122

是的,你可以,但只适用于整型类型。 如果你想要静态成员是其他任何类型,你必须在cpp文件中定义它。

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";

此外,请注意,这个规则已经在C++11中被删除了,现在(如果编译器提供该功能),您可以直接在类成员声明中初始化所需内容。

2
@anarhikos - 在类内初始化仅适用于整数类型。 double 不是整数类型。 - Brian Neal
2
@anrhikos:这就是为什么你不应该在类内部定义。作为一种惯例,你应该在类外部定义(请参见我的答案)。 - user195488
如果我不想分配一个值怎么办?如果我只想运行默认构造函数呢?如果我什么都不分配,就会得到关于在类外重新声明变量的错误。 - Ben Farmer
5
@anarhikos,你需要在static const(C++17)之前加上inline,或者使用constexpr。 - Zhang
4
如果这个答案能够扩展到你需要在C++11或C++17中做什么,那就太好了。基本上是将@Zhang的评论添加到答案中。 - C. Binair

40

静态数据成员(仅限C ++)

在类的成员列表中声明静态数据成员不是定义。您必须在命名空间范围内定义静态成员,而不是在类声明中。例如:

class X
{
public:
      static int i;
};
int X::i = 0; // definition outside class declaration

一旦你定义了一个静态数据成员,即使静态数据成员的类不存在任何对象,它仍然存在。在上面的例子中,尽管已经定义了静态数据成员X::i,但类X的对象并不存在。

命名空间范围内的类的静态数据成员具有外部链接性。静态数据成员的初始化程序处于声明该成员的类的作用域内。

静态数据成员可以是除void或void限定为const或volatile的任何类型。你不能将静态数据成员声明为mutable。

程序中只能有一个静态成员的定义。无名类、包含在无名类中的类和局部类不能具有静态数据成员。

静态数据成员及其初始化器可以访问其类的其他静态私有和保护成员。下面的示例显示如何使用其他静态成员初始化静态成员,即使这些成员是私有的:

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

由于y是从私有派生的类的对象,其成员对C类的成员不可访问,所以C::p和C::q的初始化会导致错误。

如果静态数据成员是const整数或const枚举类型,则可以在静态数据成员的声明中指定常量初始化程序。这个常量初始化程序必须是一个整数常量表达式。请注意,常量初始化程序不是定义。您仍然需要在封闭命名空间中定义静态成员。以下示例演示了此问题:

#include <iostream>
using namespace std;

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

const int X::a;

int main() {
  cout << X::a << endl;
}

在静态数据成员a的声明末尾,tokens = 76是一个常量初始化器。


21

为了完整起见,我要补充一下关于静态模板成员变量的内容。

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

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

int main(){
   X<int> x;
}

2
感谢@Chubsdad的分享!找到正确的语法非常困难。 - user

7

你不能在构造函数中初始化静态成员。整型可以在声明时内联初始化。其他静态成员必须在 .cpp 文件中定义:

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

// .cpp
const foo A::bar = ...;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接