我从未真正理解为什么c++需要一个单独的头文件,其中包含与.cpp文件中相同的函数。它使得创建类和重构类变得非常困难,并且给项目添加了不必要的文件。还有一个必须包含头文件的问题,但是必须显式地检查它是否已经被包含。

c++在1998年被批准,那么为什么要这样设计呢?使用单独的头文件有什么好处?


后续问题:

当我所包含的是.h文件时,编译器如何找到其中的代码的.cpp文件?它是假定.cpp文件与.h文件具有相同的名称,还是实际上遍历目录树中的所有文件?


当前回答

我认为头文件背后的真正(历史)原因是使编译器开发人员更容易……但是,头文件确实有优势。 查看之前的帖子了解更多讨论…

其他回答

它不需要一个与main中相同功能的单独头文件。只有在使用多个代码文件开发应用程序以及使用之前未声明的函数时才需要它。

这真的是一个范围问题。

第一个优点:如果没有头文件,就必须在其他源文件中包含源文件。这将导致在包含的文件更改时重新编译包含的文件。

第二个优点:它允许在不同的单元(不同的开发人员、团队、公司等)之间共享接口而无需共享代码。

有些人认为头文件是一种优势:

It is claimed that it enables/enforces/allows separation of interface and implementation -- but usually, this is not the case. Header files are full of implementation details (for example member variables of a class have to be specified in the header, even though they're not part of the public interface), and functions can, and often are, defined inline in the class declaration in the header, again destroying this separation. It is sometimes said to improve compile-time because each translation unit can be processed independently. And yet C++ is probably the slowest language in existence when it comes to compile-times. A part of the reason is the many many repeated inclusions of the same header. A large number of headers are included by multiple translation units, requiring them to be parsed multiple times.

归根结底,头文件系统是70年代C语言刚被设计出来时的产物。当时,计算机的内存非常少,将整个模块保存在内存中是不可能的。编译器必须从文件顶部开始读取,然后线性地遍历源代码。报头机制支持这一点。编译器不需要考虑其他翻译单元,它只需要从上到下读取代码。

c++为了向后兼容而保留了这个系统。

今天,这毫无意义。它效率低下,容易出错,而且过于复杂。如果目标是分离接口和实现,还有更好的方法。

然而,c++ 0x的建议之一是添加一个适当的模块系统,允许代码像。net或Java那样被编译成更大的模块,所有这些都是一次性的,而且没有头文件。这个提议在c++ 0x中没有被采纳,但我相信它仍然属于“我们希望以后再做这个”的范畴。也许在TR2或类似的地方。

您似乎在询问如何将定义与声明分开,尽管头文件还有其他用途。

答案是c++不“需要”这个。如果将所有内容都标记为内联(对于类定义中定义的成员函数来说,这是自动的),则不需要分离。你可以在头文件中定义一切。

你想分手的原因可能是:

改善构建时间。 在没有定义源的情况下链接到代码。 避免将所有内容标记为“内联”。

如果你更普遍的问题是,“为什么c++和Java不一样?”,那么我不得不问,“为什么你写c++而不是Java?”- p;

但是,更严重的是,c++编译器不能像javac那样直接进入另一个翻译单元,并找出如何使用它的符号。头文件需要向编译器声明在链接时它期望可用的内容。

所以#include是一个直接的文本替换。如果你在头文件中定义所有东西,预处理器最终会对项目中的每个源文件创建一个巨大的复制和粘贴,并将其提供给编译器。c++标准在1998年被批准的事实与此无关,这是c++的编译环境如此紧密地基于C的事实。

转换我的评论来回答你接下来的问题:

编译器如何找到包含代码的.cpp文件

It doesn't, at least not at the time it compiles the code that used the header file. The functions you're linking against don't even need to have been written yet, never mind the compiler knowing what .cpp file they'll be in. Everything the calling code needs to know at compile time is expressed in the function declaration. At link time you will provide a list of .o files, or static or dynamic libraries, and the header in effect is a promise that the definitions of the functions will be in there somewhere.

如果你想让编译器自动找到其他文件中定义的符号,你需要强迫程序员把这些文件放在预定义的位置(就像Java包的结构决定了项目的文件夹结构)。我更喜欢头文件。此外,你还需要你所使用的库的源代码,或者一些统一的方法来把编译器需要的信息放在二进制文件中。