2016-12-04 85 views
4

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

根据一个定义规则,如在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 
}; 

如果我尝试定义bfoo(),我,不过,仅限于整个程序,我相信一个单一的定义是由于在声明3.2.4:

每个程序都应该包含该程序中每个非内联函数或变量odr-used 的一个定义;不需要诊断。

出于这个原因,下面的程序是非法的构造:

//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:

可以有外部链接(7.1.2),类模板(第14章),非静态函数模板(14.5.6),类型类型(第9章),枚举类型(7.2),内联函数的多个定义。 ,类模板(14.5.1.3)的静态数据成员 ,类模板(14.5.1.1)的成员函数或模板专用 ,某些模板参数rs未在程序中指定(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 
}; 

请不要在上面的代码中留下评论,不要直接从标准中复制。

+2

“明显允许多个'a'的定义(否则我的问题顶部的程序将无法编译)” - 大多数ODR违规是“未定义的行为,不需要诊断”,所以缺少编译错误不是证据被允许 –

+0

嗯,那是真的......我实际上更多地被规则中的(明显的)矛盾所困扰。感谢答案,我现在看到了我所缺少的。无论如何感谢突出这个细节。 – Geoffrey91

回答

3

[basic.def.odr]/1:

任何翻译单元都不得包含任何变量,函数,类类型,枚举类型或模板的多个定义。

变量由[基本]/6定义:

可变由比非静态数据成员或对象的其他的基准的声明引入。

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

+0

非常感谢的人,我错过了[基本]/6。你无法理解它给我带来的困扰!现在我终于可以放松......顺便说一句,有没有类似于与非静态数据成员相关的ODR的规则?任何我应该注意的事情(这仍然涉及到多重定义的问题)? – Geoffrey91

+1

我不认为有。类定义的主体是唯一可以定义非静态数据成员的地方,所以它已经被规则所覆盖,即每个类的定义都必须是令牌相同的标记。 – Oktalist

+0

很酷,再次感谢,祝你有个美好的一天! – Geoffrey91

0

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

如果你不能有多个声明则include是行不通的预处理简单,在每个翻译信息,它的二手拷贝

+1

每个非静态数据成员的声明都是一个定义,每[basic.def]/2。 – Oktalist

+0

是的,我同意,看我编辑的问题 – Geoffrey91