我从未真正理解为什么c++需要一个单独的头文件,其中包含与.cpp文件中相同的函数。它使得创建类和重构类变得非常困难,并且给项目添加了不必要的文件。还有一个必须包含头文件的问题,但是必须显式地检查它是否已经被包含。
c++在1998年被批准,那么为什么要这样设计呢?使用单独的头文件有什么好处?
后续问题:
当我所包含的是.h文件时,编译器如何找到其中的代码的.cpp文件?它是假定.cpp文件与.h文件具有相同的名称,还是实际上遍历目录树中的所有文件?
我从未真正理解为什么c++需要一个单独的头文件,其中包含与.cpp文件中相同的函数。它使得创建类和重构类变得非常困难,并且给项目添加了不必要的文件。还有一个必须包含头文件的问题,但是必须显式地检查它是否已经被包含。
c++在1998年被批准,那么为什么要这样设计呢?使用单独的头文件有什么好处?
后续问题:
当我所包含的是.h文件时,编译器如何找到其中的代码的.cpp文件?它是假定.cpp文件与.h文件具有相同的名称,还是实际上遍历目录树中的所有文件?
当前回答
它不需要一个与main中相同功能的单独头文件。只有在使用多个代码文件开发应用程序以及使用之前未声明的函数时才需要它。
这真的是一个范围问题。
其他回答
您似乎在询问如何将定义与声明分开,尽管头文件还有其他用途。
答案是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.
c++是在1998年被批准的,但它的使用时间比那要长得多,而且批准主要是规定当前的用法,而不是强加结构。由于c++是基于C语言的,而C语言有头文件,所以c++也有头文件。
使用头文件的主要原因是支持文件的单独编译,并最小化依赖关系。
假设我有foo.cpp,我想使用bar.h/bar.cpp文件中的代码。
我可以在foo.cpp中#包含“bar.h”,然后编程和编译foo.cpp,即使bar.cpp不存在。头文件向编译器承诺bar.h中的类/函数将在运行时存在,并且它已经拥有了它需要知道的一切。
当然,如果bar.h中的函数没有body当我试图链接我的程序时,它就不会链接,我就会得到一个错误。
一个副作用是,您可以在不透露源代码的情况下为用户提供头文件。
另一种情况是,如果更改了*.cpp文件中代码的实现,但根本不更改头文件,则只需要编译*.cpp文件,而不需要编译使用它的所有内容。当然,如果您在头文件中放置了大量的实现,那么这就变得不那么有用了。
第一个优点:如果没有头文件,就必须在其他源文件中包含源文件。这将导致在包含的文件更改时重新编译包含的文件。
第二个优点:它允许在不同的单元(不同的开发人员、团队、公司等)之间共享接口而无需共享代码。
它不需要一个与main中相同功能的单独头文件。只有在使用多个代码文件开发应用程序以及使用之前未声明的函数时才需要它。
这真的是一个范围问题。
c++是这样做的,因为C是这样做的,所以真正的问题是为什么C要这样做?维基百科对此做了一些说明。
较新的编译语言(例如 Java、c#)不使用转发 声明;标识符 从源自动识别 文件和读取直接从动态 符号库。这意味着头文件 不需要文件。