我从未真正理解为什么c++需要一个单独的头文件,其中包含与.cpp文件中相同的函数。它使得创建类和重构类变得非常困难,并且给项目添加了不必要的文件。还有一个必须包含头文件的问题,但是必须显式地检查它是否已经被包含。
c++在1998年被批准,那么为什么要这样设计呢?使用单独的头文件有什么好处?
后续问题:
当我所包含的是.h文件时,编译器如何找到其中的代码的.cpp文件?它是假定.cpp文件与.h文件具有相同的名称,还是实际上遍历目录树中的所有文件?
我从未真正理解为什么c++需要一个单独的头文件,其中包含与.cpp文件中相同的函数。它使得创建类和重构类变得非常困难,并且给项目添加了不必要的文件。还有一个必须包含头文件的问题,但是必须显式地检查它是否已经被包含。
c++在1998年被批准,那么为什么要这样设计呢?使用单独的头文件有什么好处?
后续问题:
当我所包含的是.h文件时,编译器如何找到其中的代码的.cpp文件?它是假定.cpp文件与.h文件具有相同的名称,还是实际上遍历目录树中的所有文件?
当前回答
我认为头文件背后的真正(历史)原因是使编译器开发人员更容易……但是,头文件确实有优势。 查看之前的帖子了解更多讨论…
其他回答
以我的理解(有限的-我通常不是一个C开发人员),这是植根于C。记住,C不知道类或名称空间是什么,它只是一个很长的程序。另外,在使用函数之前必须声明它们。
例如,下面应该给出一个编译器错误:
void SomeFunction() {
SomeOtherFunction();
}
void SomeOtherFunction() {
printf("What?");
}
错误应该是“SomeOtherFunction未声明”,因为您在声明它之前调用了它。解决这个问题的一种方法是将SomeOtherFunction移到SomeFunction之上。另一种方法是先声明函数的签名:
void SomeOtherFunction();
void SomeFunction() {
SomeOtherFunction();
}
void SomeOtherFunction() {
printf("What?");
}
这让编译器知道:在代码的某个地方,有一个名为SomeOtherFunction的函数返回void,不接受任何参数。因此,如果您遇到试图调用SomeOtherFunction的代码,不要惊慌,而是去寻找它。
现在,假设在两个不同的.c文件中有SomeFunction和SomeOtherFunction。然后你必须在Some.c中#包含“SomeOther.c”。现在,向other .c中添加一些“私有”函数。由于C不知道私有函数,因此该函数也可以在Some.c中使用。
这就是.h文件的作用:它们指定你想从一个.c文件中“导出”的所有函数(和变量),这些函数可以在其他.c文件中访问。这样,您就获得了类似于Public/Private作用域的东西。此外,您可以将这个.h文件提供给其他人,而不必共享您的源代码- .h文件也适用于编译过的.lib文件。
主要原因是为了方便,为了源代码保护和应用程序各部分之间的解耦。
那是C。c++引入了类和私有/公共修饰符,所以当你仍然可以询问是否需要它们时,c++ AFAIK仍然要求在使用它们之前声明函数。此外,许多c++开发人员也是或曾经是C开发人员,并将他们的概念和习惯转移到c++中——为什么要改变没有破坏的东西呢?
c++的设计目的是在C基础设施中添加现代编程语言的特性,而无需不必要地更改C语言中与语言本身无关的任何内容。
是的,在这一点上(在第一个c++标准诞生10年之后,在它开始大量使用20年之后),很容易会问为什么它没有一个合适的模块系统。很明显,现在设计的任何新语言都不能像c++那样工作。但这不是c++的意义所在。
c++的重点是进化,是现有实践的平稳延续,只是添加新的功能,而不(经常)破坏对用户社区来说足够有效的东西。
这意味着,与其他语言相比,它使一些事情变得更困难(特别是对于开始一个新项目的人),而另一些事情则更容易(特别是对于维护现有代码的人)。
因此,与其期待c++变成c#(这毫无意义,因为我们已经有了c#),为什么不选择正确的工具来完成这项工作呢?就我自己而言,我努力用现代语言(我碰巧使用c#)编写大量的新功能,并且我有大量现有的c++,我将它们保存在c++中,因为重新编写它们将没有真正的价值。它们融合得很好,所以基本上是无痛的。
第一个优点:如果没有头文件,就必须在其他源文件中包含源文件。这将导致在包含的文件更改时重新编译包含的文件。
第二个优点:它允许在不同的单元(不同的开发人员、团队、公司等)之间共享接口而无需共享代码。
它不需要一个与main中相同功能的单独头文件。只有在使用多个代码文件开发应用程序以及使用之前未声明的函数时才需要它。
这真的是一个范围问题。
你可以在没有头文件的情况下完美地开发c++。事实上,一些大量使用模板的库并不使用头文件/代码文件范例(参见boost)。但是在C/ c++中,你不能使用没有声明的东西。一个实用的方法 处理这个问题的方法就是使用头文件。此外,您还可以在不共享代码/实现的情况下共享接口。我认为这不是C语言的创造者所能想象到的:当你使用共享头文件时,你必须使用著名的:
#ifndef MY_HEADER_SWEET_GUARDIAN
#define MY_HEADER_SWEET_GUARDIAN
// [...]
// my header
// [...]
#endif // MY_HEADER_SWEET_GUARDIAN
这并不是真正的语言特性,而是处理多重包含的一种实用方法。
所以,我认为在创建C时,前向声明的问题被低估了,现在当使用像c++这样的高级语言时,我们必须处理这类事情。
对于我们这些可怜的c++用户来说,这又是一个负担……