简体   繁体   English

C++ 包含文件

[英]C++ Include files

I understand that providing a definition in a header file allows other files to reference them and then the linker adds all the object files together and provides the definitions later.我知道在头文件中提供定义允许其他文件引用它们,然后链接器将所有目标文件添加在一起并稍后提供定义。

Is this just so that we can reuse the implementation else where in other libraries?这只是为了我们可以在其他库中的其他地方重用实现吗?

If we didnt use header files or abused them and put all the code in them, ie The full implementation what would happen?如果我们不使用头文件或滥用它们并将所有代码都放在其中,即完整的实现会发生什么? Would it take longer when compiling each file as the full definition would need to be compiled on a peer file basis?编译每个文件时是否需要更长的时间,因为需要在对等文件的基础上编译完整定义? Would it cause issues with the linker as the would be multiple compiled versions of the same implementaion?它会导致链接器出现问题,因为它是同一实现的多个编译版本吗?

How does this work with templates?这如何与模板一起使用?

Blair布莱尔

Any code placed in your header file gets compiled every time a new compilation target includes that header file, so at a minimum yes, you will take longer to compile.每次新的编译目标包含该头文件时,头文件中的任何代码都会被编译,因此至少是的,您将花费更长的时间来编译。 This is not the significant problem generally though.不过,这通常不是重要的问题。

Lets say you have this header:假设你有这个标题:

int f_header() {
    return 0;
}

And these source files:以及这些源文件:

/* a.cpp */
#include "myheader.h"
int f_a() {
    return f_header();
}


/* b.cpp */
#include "myheader.h"
int f_b() {
    return f_header();
}

Now, when you compile each of these sources the compilation will succeed.现在,当您编译这些源代码中的每一个时,编译都会成功。 However when you link your program, the linker will fail because you will have provided the function f_header() twice.但是,当您链接程序时,链接器将失败,因为您将提供函数f_header()两次。

Templates are a special case since they are not actually code, but rather they provide a template for code to be generated based on different types.模板是一种特殊情况,因为它们实际上并不是代码,而是为基于不同类型生成的代码提供了模板。 Though there is the appearance of duplication when multiple source files use them with the same types, the compiler is able to handle this special case for you.尽管当多个源文件使用相同类型的源文件时会出现重复,但编译器能够为您处理这种特殊情况。

Splitting up the code in source and header files was (is?) more or less historically required.拆分源文件和头文件中的代码是(是?)历史上或多或少需要的。 It allowed the compiler to compile code units of big projects separately, where the whole project would have been too big to be compiled at once.它允许编译器单独编译大项目的代码单元,整个项目太大而无法一次编译。

And it allows to cache compilation units that haven't changed, which further improved compilation time.它允许缓存没有改变的编译单元,这进一步缩短了编译时间。

So technically, the compiler sees a whole set of different compilation units.所以从技术上讲,编译器会看到一整套不同的编译单元。 If you provide multiple implementations of the same definition, it's nothing the compiler could tell you.如果您提供相同定义的多个实现,则编译器不会告诉您什么。 But the linker will stumble over it, once it wraps up the compiled units to a single executable file.但是一旦链接器将编译单元包装成单个可执行文件,它就会绊倒它。

Today, "modern" languages like C# or Java moved away from this historical constraints.今天,像 C# 或 Java 这样的“现代”语言摆脱了这种历史限制。 But C++ is a complicated language, even for the compiler, so these advantages are still relevant somehow.但是 C++ 是一种复杂的语言,即使对于编译器也是如此,所以这些优势在某种程度上仍然是相关的。

Compiler compiles one file at a time.编译器一次编译一个文件。 The source file that compiler is parsing may include other files, but all those included files are "flatten" into single source during pre-compile phase, and the compiler "sees" one single code entity.编译器正在解析的源文件可能包含其他文件,但所有这些包含的文件在预编译阶段都被“扁平化”为单个源,并且编译器“看到”一个单一的代码实体。

Because of the above it does not matter to the compiler if the code is in .cpp or in .h file, because the compiler does not make that distinction.由于上述原因,代码是在 .cpp 还是在 .h 文件中对编译器来说无关紧要,因为编译器不会进行区分。 But if some function definition or some variable definition is in .h file the problem ensues in link phase.但是如果一些函数定义或一些变量定义在 .h 文件中,问题就会出现在链接阶段。

Linker does not see source files, but it does see object files (.obj), which are the result that compiler produces.链接器看不到源文件,但可以看到目标文件 (.obj),这是编译器生成的结果。 Linker is aware of every function and every variable in each object file, and linkers job is to bind (or link) them all together in a single executable.链接器知道每个目标文件中的每个函数和每个变量,而链接器的工作是将它们全部绑定(或链接)在一个可执行文件中。 If there are several variables or functions with the same name in different object files linker is at loss of what to do with them, and it will declare an error.如果在不同的目标文件中有多个同名的变量或函数,链接器将无所适从,并且会声明错误。 It is possible to force linker with an option to ignore all extra variables and functions, but that option is not to be used lightly.可以通过一个选项强制链接器忽略所有额外的变量和函数,但不要轻易使用该选项。 Two functions with the same name may actually be completely different, and ignoring one of them will lead to all sorts of errors.两个同名的函数实际上可能完全不同,忽略其中一个会导致各种错误。

Templates on the other hand are not functions at all.另一方面,模板根本不是函数。 They are blueprints for actual functions.它们是实际功能的蓝图。 Nothing substantial will happen when compiler encounters a template.当编译器遇到模板时,不会发生任何实质性的事情。 Only when a template is instantiated to an actual function the compiler will make such a function.只有当模板实例化为实际函数时,编译器才会生成这样的函数。 Because of this templates can reside in header files just fine.因为这个模板可以驻留在头文件中就好了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM