非静态数据成员和一个定义规则

时间:2016-12-04 19:11:04

标签: c++ class scope linkage one-definition-rule

前提

根据一个定义规则,如C++14 Standard中所述,只要我遵循3.2中的规则,我就可以在每个翻译单元中定义相同的类别0.6。这意味着允许以下程序合法:

//a_1.cpp
class A {                      //definition of A
    int a;                     //definition of A::a
    static int b;              //declaration of A::b
    int foo();                 //declaration of A::foo();
    int boo(){ return 42; };   //definition of A::boo() implicity inlined 
};

//a_2.cpp
class A {                      //definition of A
    int a;                     //definition of A::a
    static int b;              //declaration of A::b
    int foo();                 //declaration of A::foo();
    int boo(){ return 42; };   //definition of A::boo() implicity inlined 
};

如果我尝试定义bfoo(),我可能只限于整个程序中的单个定义,我认为这是由于3.2.4中的陈述:

  

每个程序都应该包含每个非内联函数或odr使用的变量的一个定义   在该计划中;无需诊断。

因此,以下程序格式不正确:

//a_1.cpp
class A {                      //definition of A
    int a;                     //definition of A::a
    static int b;              //declaration of A::b
    int foo();                 //declaration of A::foo();
    int boo(){ return 42; };   //definition of A::boo() implicity inlined 
};
int A::b;

//a_2.cpp
class A {                      //definition of A
    int a;                     //definition of A::a
    static int b;              //declaration of A::b
    int foo();                 //declaration of A::foo();
    int boo(){ return 42; };   //definition of A::boo() implicitly inlined 
};
int A::b;

如果我尝试在两个源文件中定义foo(),则相同。

然而,我可以有boo()的多个定义(每个翻译单元一个),因为这不是3.2.4所禁止的,实际上,3.2.6明确允许:

  

类类型(第9条),枚举类型(7.2),内联函数可以有多个定义   外部链接(7.1.2),类模板(第14章),非静态函数模板(14.5.6),静态数据成员   类模板(14.5.1.3),类模板的成员函数(14.5.1.1)或模板特化   其中一些模板参数未指定(14.7,14.5.5),在程序中提供了每个定义   出现在不同的翻译单元中。

公平地说,3.2.6限定了上面的声明,增加了一些要求,其中实体(在我们的例子中是boo())必须在每个翻译单元中使用相同的令牌序列来定义。

问题

非静态数据成员a怎么样?显然允许a的多个定义(否则我的问题顶部的程序将无法编译),但这似乎是3.2.4禁止的,而不是3.2.6的宽容。这只是标准中没有严格规定的细节,还是我遗漏了什么?

修改

对于那些向我表明a未定义但刚刚宣布的人,请考虑这个例子,直接来自C++14 Standard,3.2.2:

struct X { // defines X
    int x; // defines non-static data member x
    static int y; // declares static data member y
    X(): x(0) { } // defines a constructor of X
};

请注意,上述代码的评论不是我的,而是直接从标准中复制。

1 个答案:

答案 0 :(得分:0)

第一个程序中没有a的多个定义。您有a的多个声明。巨大的差异。

如果您无法进行多次声明,则include将无效,因为预处理器只是在其使用的每次翻译中复制该信息。