我知道什么是头文件,但是,我仍然不明白为什么许多程序员制作一个头文件,一个同名的源文件,只有原型函数头文件,同时告诉该函数在源文件中做了什么。
我从不在单独的文件中创建函数及其原型,只需将其全部放入头文件中。
问题是,为什么要为标题创建源文件?它是否有任何优势?是否只是为了使代码看起来更干净?我不明白。
答案 0 :(得分:10)
如果在标题中实现函数,然后将标题包含在两个或多个不同的源文件中,则您将拥有相同函数的多个定义。这违反了一个定义规则。
可以通过声明内联函数来解决这个问题,但是(除非链接器知道如何合并多个定义)可能会导致代码膨胀。
答案 1 :(得分:6)
您通常在标题中定义(不仅声明)inlined functions。
并声明非内联函数(例如,其主体足够大的函数),并在一个特定的编译单元中定义它们(即实现它们)。
然后链接器在链接时解析相应的函数名称(通常为mangled names)。并且您不希望具有多重定义的函数。
只有一个编译单元提供的函数定义使总构建时间更快一些。
使用link-time optimizations(例如编译期间和链接期间-flto
g++
选项)事情变得更加复杂。
请注意,巨大的软件(一些可执行文件几乎是1千兆字节的二进制文件,只需将它们链接几分钟)就会带来一些单独的程序员甚至无法想象的限制。试着从源代码中编译一个大型免费软件(Libreoffice,Firefox,Qt5,...)来猜测问题。
顺便说一下,你原则上可以将某些程序的所有代码放在一个源文件中,但出于有效和明显的原因,人们不这样做。答案 2 :(得分:4)
在使用任何非平凡的系统时,将函数定义放入标题会导致冗长的编译时间。它可能适用于小型项目来制作所有内容inline
,但它肯定不适用于更大的系统(更不用说拥有几亿行代码的大型系统)。
答案 3 :(得分:1)
头文件中的函数声明提供了可用于将代码链接在一起的符号引用。编译单个源文件时,每个源文件都会生成为目标代码。
如果要在另一个源文件中使用一个源的函数,则需要一些方法来了解该代码的位置以及如何调用它。出于这个原因,编译器能够使用函数声明。它知道如何调用它以及它返回的内容,但它还不知道函数的来源在哪里。
将所有源代码编译成目标代码后,链接器会将所有目标文件组装成可执行文件(或库),并解析这些符号引用。
答案 4 :(得分:0)
如果您将所有代码都放在一个非共享文件中,那么它在标题或源文件中的位置无关紧要。
将代码拆分为标头和源文件有两个主要原因。它们可以这样概括:
<强>技术即可。如果您有多个源文件相互交互,则需要包含标头。如果您在标题中定义了所有内容,那么您将包含多个代码定义 - 这是编译错误。
<强>设计即可。头文件定义了软件的接口,可以在不暴露内部实现的情况下分发给客户端软件。