类静态变量的初始化顺序

时间:2018-07-11 07:08:58

标签: c++ scope language-lawyer

我有一个具有两个静态变量的A类。我想用另一个不相关的静态变量来初始化一个,就像这样:

#include <iostream>
class A
{
public:
    static int a;
    static int b;
};

int A::a = 200;
int a = 100;
int A::b = a;
int main(int argc, char* argv[])
{
    std::cout << A::b << std::endl;

    return 0;
}

输出为200。那么,有人可以告诉我为什么吗?

4 个答案:

答案 0 :(得分:36)

根据查找规则,这是正确的。 [basic.lookup.unqual]/13说:

  

在类X的静态数据成员的定义中使用的名称   (在静态成员的qualified-id之后)查找,就像   名称在X的成员函数中使用。[注:[class.static.data]   进一步描述了名称中使用名称的限制   静态数据成员的定义。 —尾注]

由于查找不合格的a就像您在成员函数中一样,因此必须首先找到成员A::aA::aA::b的初始化顺序虽然会影响结果的定义程度,但不会影响查找。

答案 1 :(得分:16)

  

那么,谁能告诉我为什么?

basic.scope.class/4中对此进行了明确说明,重点是:

  

延伸到末尾或超出末尾的声明的潜在范围   类定义的扩展到由其定义的区域   成员定义,即使成员在词汇表外部定义   类(此包括静态数据成员定义,嵌套类   定义和成员函数定义,包括成员   函数体以及此类的声明器部分的任何部分   声明符编号之后的定义,包括   参数声明子句和任何默认参数)。

因此,当您拥有

int A::a = 200;
int a = 100;
int A::b = a; // note the '::' scope resolution operator
              // OUTPUT: 200

a实际上是指A::a,因为类范围A::b 扩展

不同于您是否拥有:

int A::a = 200;
int a = 100;
int b = a; // note b is not A::b
           // i.e. without the '::', scope resolution operator
           // OUTPUT: 100

a指的是(全局)::a,因为此处的b不是class A的成员,
即没有类范围扩展。

答案 2 :(得分:8)

c++draft/class.static

  

如果在静态成员的定义中使用了unqualified-id,则该成员的声明者ID 之后,和名称查找([basic.lookup.unqual])会发现该不合格ID -id是成员类(或成员类的基类)的静态成员,枚举器或嵌套类型,未限定ID会转换为限定ID表达式,其中nested-name-specifier命名引用成员的类范围。 [注意:有关使用非静态数据成员和非静态成员函数的限制,请参见[expr.prim.id]。 —尾注]

它表示在您遇到的情况下,unqualified-id会转换为qualified-id表达式。

int A::b = a;

您可以设置qualified-id,但没有这样的嵌套名称说明符。

int A::b = ::a;

答案 3 :(得分:6)

因为名称查找将a解析为A::a。如果要执行此操作,则需要手动解决范围:

int A::b = ::a;
        // ^ Global scope resolution

Live Example