标头和ODR中的类定义? [英] Class definitions in headers and ODR?

查看:49
本文介绍了标头和ODR中的类定义?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,由于ODR,我们将类定义放在标头中,并且不包括转换单元而不是标头(可能有更多原因).另外,由于ODR,您不应在标头中添加变量和函数等的定义,因为它可能会违反规则....

So we put class definitions in headers and we do not include translation units rather than headers because of the ODR (there probably are more reasons). Also, because of the ODR, you should not add definitions of variables and functions etc. in headers because it is likely to break the rule....

但是,由于 ODR也适用于类类型(我是类定义),为什么可以不加小心地将其添加到标头中?

But since ODR also applies for class types (which to me is class definitions), why can that be added in headers without caution?

推荐答案

标准的"3.2 Ondefinition rule"部分中有几条语句,涉及该规则的不同方面.

There are several statements in the "3.2 Ondefinition rule" section of the standard, that covers different aspects of the rule.

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

此内容涵盖了您问题中的类类型定义,但这仅适用于一个翻译单元(或源文件).包含在不同文件(翻译单元)中的标头中的相同类类型定义不会违反此定义,因为它涉及多个翻译单元(并且在任何一个翻译单元中仍然只有一个定义).

This one covers the class type definition in your question, but this only applies to one translation unit (or source file). The same class type definition in the header included in different files (translations units) does not violate this, as it involves multiple-translations units (and there is still only one definition in any one of the translation units).

  1. 每个程序应准确地包含该程序中使用的每个非内联函数或变量的一个定义;无需诊断.该定义可以显式出现在程序中,可以找到在标准库或用户定义的库中,或者(如果适用)隐式定义(请参见12.1、12.4和12.8).内联函数应在使用过的每个翻译单元中定义.

此规则涵盖了程序级别(可能包含多个翻译单元),但仅影响已习惯使用的非内联函数或可行.没有涵盖不同翻译单元中包含的类类型定义,并且不违反此规则.

This rule covers the program level (may contain several translation units), but it only affects non-inline function or viable that are odr-used. Class type definition included in different translation units is not covered and does not violate this rule.

而且,有一条规则专门处理出现在不同翻译单元中的类类型的定义:

And, there is a rule that specifically deals with definitions of a class type appearing in different translation units:

  1. 一个类类型(第9章),枚举类型(7.2),具有外部链接的内联函数(7.1.2),类模板(第14章),非静态函数可以有多个定义模板(14.5.6),静态数据成员类模板(14.5.1.3),类模板的成员函数(14.5.1.1)或未在程序中指定某些模板参数(14.7、14.5.5)的模板专门化(前提是每个定义都出现在模板中)不同的翻译单位,并提供符合以下要求的定义.如果给这样一个名为D的实体定义了多个翻译单元,则

  1. 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, and provided the definitions satisfy the following requirements. Given such an entity named D defined in more than one translation unit, then

  • D的每个定义应由相同的令牌序列组成;和
  • 在D的每个定义中,按照3.4查找的相应名称中的
  • ,应指代D定义内定义的实体,或指代在重载解析(13.3)和部分模板匹配后的相同实体.专业化(14.8.3),只是名称可以引用const对象如果对象在D的所有定义中都具有相同的文字类型,并且使用常量表达式(5.19)初始化该对象,并且使用该对象的值(而不是地址),则使用内部链接或不使用内部链接在D的所有定义中具有相同的值;和
  • 在D的每个定义中,相应的实体应具有相同的语言链接;和
  • 在D的每个定义中,所引用的重载运算符,对转换函数,构造函数,运算符新函数和运算符delete函数的隐式调用,应引用相同的函数或D定义内定义的函数;和
  • 在D的每个定义中,(隐式或显式)函数调用使用的默认参数被视为D的定义中存在其令牌序列;也就是说,默认参数要遵守上述三个要求(并且,如果默认参数具有带有默认参数的子表达式,则此要求将递归地应用).
  • 如果D是具有隐式声明的构造函数(12.1)的类,则好像该构造函数是在odr所使用的每个翻译单元中隐式定义的,并且每个翻译单元中的隐式定义应调用相同的D的基类或类成员的构造函数.
  • each definition of D shall consist of the same sequence of tokens; and
  • in each definition of D, corresponding names, looked up according to 3.4, shall refer to an entity defined within the definition of D, or shall refer to the same entity, after overload resolution (13.3) and after matching of partial template specialization (14.8.3), except that a name can refer to a const object with internal or no linkage if the object has the same literal type in all definitions of D, and the object is initialized with a constant expression (5.19), and the value (but not the address) of the object is used, and the object has the same value in all definitions of D; and
  • in each definition of D, corresponding entities shall have the same language linkage; and
  • in each definition of D, the overloaded operators referred to, the implicit calls to conversion functions, constructors, operator new functions and operator delete functions, shall refer to the same function, or to a function defined within the definition of D; and
  • in each definition of D, a default argument used by an (implicit or explicit) function call is treated as if its token sequence were present in the definition of D; that is, the default argument is subject to the three requirements described above (and, if the default argument has sub-expressions with default arguments, this requirement applies recursively).
  • if D is a class with an implicitly-declared constructor (12.1), it is as if the constructor was implicitly defined in every translation unit where it is odr-used, and the implicit definition in every translation unit shall call the same constructor for a base class or a class member of D.

简而言之,您可以在不同的翻译单元中多次定义类类型,但是每个翻译单元最多可以有一个定义,并且所有定义必须相同.

In short, you can define the class type multiple times in different translation units, but each translation unit can have at most one definition, and all the definitions must be the same.

这篇关于标头和ODR中的类定义?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆