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

non-static data members and one definition rule

前提

根据一个定义规则,如C++14 Standard所述,我可以在每个翻译单元中定义相同的class只要我遵守 3.2.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 中的声明:

Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program; no diagnostic required.

因此,以下程序格式错误:

//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 明确允许:

There can be more than one definition of a class type (Clause 9), enumeration type (7.2), inline function with external linkage (7.1.2), class template (Clause 14), non-static function template (14.5.6), static data member of a class template (14.5.1.3), member function of a class template (14.5.1.1), or template specialization for which some template parameters are not specified (14.7, 14.5.5) in a program provided that each definition appears in a different translation unit.

为了公平起见,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
};

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

您在第一个程序中没有 a 的多个 定义 。您有 a 的多个 声明 。差别很大。

如果您不能有多个声明,那么 include 将无法工作,因为预处理器只是在它使用的每个翻译中复制该信息。

[basic.def.odr]/1:

No translation unit shall contain more than one definition of any variable, function, class type, enumeration type, or template.

变量定义为[basic]/6:

A variable is introduced by the declaration of a reference other than a non-static data member or of an object.

因此,由于非静态数据成员不是变量、函数、class、枚举或模板,所以单一定义规则根本不适用于非静态数据成员。