【发布时间】:2017-04-19 03:39:43
【问题描述】:
前提
按照一个定义规则,如C++14 Standard中所说,只要我遵循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
};
如果我尝试定义b 或foo(),那么我将被限制在整个程序中的单一定义,我认为这是由于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
};
请注意,上面代码的 cmets 不是我的,而是直接从标准中复制的。
【问题讨论】:
-
“
a的多个定义显然是允许的(否则我的问题顶部的程序将无法编译)” - 大多数 ODR 违规是“未定义的行为,不需要诊断”,因此缺乏编译错误不是被允许的证据 -
嗯,那是真的......我实际上对规则中的(明显的)矛盾更加困扰。多亏了答案,我现在明白了我错过了什么。无论如何,感谢您强调这个细节。
标签: c++ class scope linkage one-definition-rule