c++中的源文件和头文件
我对 C++ 中的源文件和标头有疑问.
I have a question about source file and header in c++.
我有一个用于声明函数的标头.我在 C++ 中实现了这些功能.
I have a header which is used to declare the functions. And I implement these functions in C++.
现在我需要在其他文件中使用这些函数.是否应该同时包含源文件和头文件才能使用这些功能?
Now I need to use these functions in other files. Should I include both source file and header file in order to use these functions?
推荐答案
(C 和)C++ 使用的基本编译模型如下:
The basic compilation model used by (C and) C++ is thus:
- 你把 在源文件之间共享的声明到头文件中.需要访问这些声明的源文件然后包括这些头文件.
- 编译时,预处理器将(递归地)用包含的文件替换
#include
指令.结果称为编译单元. - 然后编译器将这些编译单元一次一个编译成目标文件.(注意:编译器总是只看到一个翻译单元.它无法访问在其他翻译单元中声明和定义的任何内容.)基本上,目标文件是易于编译的代码,但所有引用编译单元之外的符号(函数、变量)仍然是符号的.
- 然后将链接器传递给所有目标文件,并将这些目标文件中对符号的引用链接到符号的definitions,如果一切顺利,会输出一个可执行文件.
- You put declarations that are to be shared between source files into header files. The source files that need to access those declarations then include these header files.
- When compiling, the preprocessor will (recursively) replace
#include
directives with the file(s) included. The result is called a compilation unit. - The compiler then compiles these compilation units, one at a time, into object files. (Note: The compiler always only ever sees a single translation unit. It has no access to whatever is declared and defined in other translation units.) Basically, object files are readily compiled code, but all the references to symbols (functions, variables) outside of their compilation unit are still symbolic.
- The linker is then passed all object files and links references to symbols across those object files to the symbols' definitions, spitting out an executable if all goes well.
在 C++ 中,这在实践中通常会稍微复杂一些(尤其是由于内联和模板,还有链接时代码生成等功能),但这是基本原则.
In C++, this is often a bit more complicated in practice (especially due to inlining and templates, but also with features like link-time code generation), but that's the basic principles.
这意味着:
- 源文件通常只包含头文件.
由于整个预处理器魔法只是一个简单的文本替换引擎,没有任何(C 或)C++ 知识以及它在上述过程中的用途,它可以被弯曲和滥用来做其他事情.在此,有时会包含源文件以实现某些目标.但这种情况很少见. - 符号可以根据需要多次声明,但必须只定义一次.
如果链接器找不到已声明的符号(因此对它的引用已被编译器接受),它将向您吐出一条令人讨厌的错误消息.如果它找到多个定义,它也会这样做. - 编译器不关心声明是来自预处理器包含的头文件还是直接写入源文件.
但是,如果您将声明直接写入源文件,则编译器无法查看"其他翻译单元,无法警告您它们已过时.如果您将声明放入头文件中,则更容易使它们与相应的定义保持同步,并且通常编译器甚至可以诊断它们是否不匹配. - 任何具有多个源文件的项目只能通过多次编译运行(每个源文件一个)来构建,其中链接器链接生成的目标文件.不过,IDE 通常会将其隐藏在项目管理背后.
如果您更改在许多源文件中直接或间接使用的标头,您将不得不重新编译大部分项目.如果更改源文件,则只需重新编译该源文件(当然,还要重新链接可执行文件).
相关文章