关于对include包含类声明或定义的文件的一些总结

来源:互联网 发布:海关出口数据怎么查询 编辑:程序博客网 时间:2024/06/08 02:38

关于对include包含类声明或定义的文件的一些总结

最近做了Matrix上的一道题目,有了两个疑惑,在查看文档以及论坛之后,解决了这两个问题,在此记录下来。

先将代码抽象出来(具体的代码不重要,所以知识模拟一下问题)

//class.cppclass sample{private:    int data;public:    void function();};void sample::function(){}//main.cpp#include "class.cpp"int main(){    return 0;}

且不论该代码include一个.cpp文件的意义
疑惑一:
上述代码编译的时候不能通过,原因是函数void function()重定义(redefinition)。我们知道c++编译的时候有编译单元这个说法,上述的两个文件就是这样的两个编译单元。这两个编译单元的单独编译不会出现问题,但是在链接(link)的时候编译器会发现有个函数被定义了两次,我们知道这是因为include的原理。

怎么解决呢?
很简单,只需将函数的定义移入类的定义的就可以了。
原因如下:
我们知道,在类里面定义的函数自动成为内联(inline)函数,而内联函数在一个程序的多个文件中是可以多次定义的
Unlike other functions, inline and constexpr functions may be defined multiple times in the program. After all, the compiler needs the definition, not just the declaration, in order to expand the code.
——from c++ primer (6.5.2)
也就是将class.cpp改成下面的样子

    //class.cppclass sample{private:    int data;public:    void function(){}};

疑惑二:
有的朋友可能会发现,class sample也被定义了两次,为什么不会导致问题呢?
查阅资料得知,c++的标准规定了在某些情况下,即使一个类被定义了多次,编译器也只把它当作一次定义。
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
— each definition of D shall consist of the same sequence of tokens; an
— 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).27
— 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.

 [ Example: //translation unit 1:struct X {X(int);X(int, int);};X::X(int = 0) { }class D: public X { };D d2; // X(int) called by D()//translation unit 2:struct X {X(int);X(int, int);};X::X(int = 0, int = 0) { }class D: public X { }; // X(int, int) called by D();// D()’s implicit definition// violates the ODR—end example ]

If D is a template and is defined in more than one translation unit, then the preceding requirements shall apply both to names from the template’s enclosing scope used in the template definition (14.6.3), and also to dependent names at the point of instantiation (14.6.2). If the definitions of D satisfy all these requirements, then the program shall behave as if there were a single definition of D. If the definitions of D do not satisfy these requirements, then the behavior is undefined.
———from iso c++11 (3.2)


(翻译太难了,请路过的大牛帮个忙)
简单来讲,我们在两个文件里定义一模一样的类两次时没有问题的。

1 0
原创粉丝点击