带有标头保护的对象文件
我对包含标头的目标文件有点困惑。我不明白如果标头防护包含在多个目标文件中,它们如何保护您。
例如:
main.o <- main.cpp class.h
class.o <- class.cpp class.h
main.exe <- main.o class.o
每个目标文件不是都包含 class.h 从而使可执行文件有两个副本吗?
I'm a bit confused about object files that contain headers. I don't see how header guards can protect you if they're included in multiple object files.
For instance:
main.o <- main.cpp class.h
class.o <- class.cpp class.h
main.exe <- main.o class.o
Wouldn't each object file contain class.h thereby making the executable have two copies of it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
你是对的,这没问题。标头防护可防止编译器看到两个副本,但不会影响链接器。事实上,链接器依赖于有两个副本的事实。毕竟,它将两者联系在一起。
You're right, and that's no problem. Header guards prevent the compiler from seeing two copies but don't affect the linker. In fact, the linker relies on the fact that there are two copies. It links those two together, after all.
目标文件不包含标头;它们包含的输出
编译器。但你提出的观点是有效的:标题中的任何内容都可能
在最终代码中重复多次。粗略地说,我们可以
区分两类:
不创建任何可能最终出现在
编译器输出:诸如 typedef 之类的东西,或者就此而言,模板
和类定义。该标准允许重复定义,
前提是它们都是“相同的”。
不允许重复的声明,以及哪些声明
不应该出现在标题中。变量和函数之类的东西。
实际上,它有点复杂,可以实例化一个模板
在多个不同来源中的同一类型上,以及实例化
模板的可以是函数。或者编译器可能无法内联
内联函数。处理这个问题的通常方法是由编译器处理
在每个翻译单元中生成函数,并让链接器
扔掉重复的。 (事实上,大多数链接器不检查是否
它们确实是重复的。他们只是扔掉所有的东西,只留下一个,被选中的
或多或少是随机的。)
Object files don't contain headers; they contain the output of the
compiler. But the point you raise is valid: anything in the header may
be duplicated several times in the final code. Roughly speaking, we can
distinguish two categories:
Declarations that don't create anything which might end up in the
compiler output: things like typedef's, or for that matter, templates
and class definitions. The standard allows duplicate definitions,
provided that they're all “identical”.
Declarations that you're not allowed to duplicate, and which
shouldn't be in a header. Things like variables and functions.
In practice, it's a bit more complex, a template may be instantiated
over the same type in several different sources, and the instantiation
of a template may be a function. Or the compiler may fail to inline an
inline function. The usual way of dealing with this is for the compiler
to generate the function in each translation unit, and for the linker to
throw out the duplicates. (In fact, most linkers don't check whether
they really are duplicates. They just throw out all but one, chosen
more or less randomly.)
头保护防止编译器两次处理头文件(这可能会生成无用的错误,因为一旦定义了类,就不允许重新定义它)。
如果头文件包含编译器实际需要为其生成代码(或数据)的内容,那么该将出现在每个目标文件中。
然后由链接器来处理这个问题,这可能会导致链接器错误(例如,如果您包含了函数的代码而没有说明它是内联的,则会导致同一函数的 2 个实例),或者没有问题(当您声明所述函数是内联的时,在这种情况下链接器将仅选择一个)。
大多数情况下,标头仅包含函数原型(不生成代码)、类定义(不生成代码)内联函数定义或外部引用。其中最后两个将在目标文件中生成需要由链接器处理的内容。
The header guard prevents the compiler processing the header file twice (which could generate unhelpful errors, as it's not permissible to redefine a class once you have a definition of it).
If the header file contains something that the compiler actually needs to generate code (or data) for, then that will occur in each object file.
It is then down to the linker to deal with that, which can result in either a linker error (if for instance you included the code for a function without saying it is inline, resulting in 2 instances of the same function), or no issue (when you stated said function was inline, in which case the linker will pick only one).
Mostly, headers only contain function prototypes (which generate no code), class definitions (which generate no code) inline function definitions, or external references. The last 2 of these will generate stuff in the object file which needs to be dealt with by the linker.