根据对此问题的回答:Why does C++ have header files and CPP
我已经看到了回答并理解了答案 - 那么为什么没有这样做呢? C#Java?
答案 0 :(得分:28)
因为它是界面与实现问题的快速,肮脏和不雅的解决方案。
它完全依赖于C预处理器,它是抽屉中最直接的工具。
其他解决方案可避免以下问题:
Dviljoen认为我很努力,而且他是对的。从打卡和纸带时代开始几乎是40-year old design。尽管存在上面列出的所有潜在问题和问题,但使用源/头文件排列的C / C ++内置了大量高质量的软件。
答案 1 :(得分:8)
因为这意味着要复制您可以从源代码中获取的信息。其他语言试图避免这种代码重复。
在我过去的C日里,我做了同样的事情。我将所有信息保存在我的.c文件中,并使用一个小工具在正常构建期间从它们生成头文件。
答案 2 :(得分:6)
对于C#,3.0 specification个状态
因为装配是一个 自描述功能单元 包含代码和元数据, 不需要#include C#中的指令和头文件。该 公共类型和成员包含在 制作一个特定的组件 只需通过C#程序即可获得 在何时引用该程序集 编制程序。
答案 3 :(得分:5)
因为它们是过去的残羹剩饭。
现代语言使用模块和包的概念。
如果要使用在另一个文件中定义的函数/类,请导入该文件。编译器会找出符号(即名称),以便您可以使用它们。
C / C ++方法:手动提取函数/类定义并将它们放在另一个文件中,然后在想要使用它们的任何地方对这些定义进行文本包含。
答案 4 :(得分:4)
在C中,你不能提出前瞻性参考,即。使用尚未在其使用之上定义的函数。标题最初是为此而制作的,作为对实现的参考。
我查看了引用问题的已接受答案,这是正确的。但今天,编译速度是一个小问题(可能除了非常大的应用程序:需要1/4小时来清理编译我们拥有的应用程序,至少在Windows上)。无论如何隐藏实现细节,我们通常只关注API文档,即。可见的界面。
对于轶事,我看到一些C ++库在头文件中实现了99%(只有系统请求它们的.cpp文件),因此模仿Java风格(C#当时不在这里......)。 / p>
答案 5 :(得分:3)
我想说,理想情况下,所有信息都应该存在于一个地方,并且有一个模块系统可以智能地避免重新编译/导入不必要的细节,然后让编译器能够在必要时提取仅接口信息(例如,运送图书馆或其他任何东西)。
答案 6 :(得分:2)
在C#和Java中并不真正需要它们,因为您可以为每个方法指定访问级别(例如公共或私有),此外您还有像C ++中那样的反射率。
请注意,对于使用头文件的非OOP实践并不是那么糟糕。例如,您可以仅在头文件中声明客户端可以公开使用哪些函数,同时通过仅在.cpp或.c文件中声明它们来隐藏其他函数(因此不可访问)。
答案 7 :(得分:2)
我想说大多数OO语言都可以通过接口获得他们所需的所有里程。它提供了头文件的所有灵活性(即 - 从实现中分离接口),同时与使用接口的客户端签订更严格的合同(因为它们由语言/编译器强制执行)。
答案 8 :(得分:1)
对我来说,C和C ++中的标题是一个很大的时间和生产力下降。编译...哎呀,忘了修复方法的签名。编译...哎呀,需要将方法a添加到类X.
答案 9 :(得分:1)
为了摆脱标题,编译器的输出需要包含编译器本身可以理解的代码描述。使用较旧的链接器并不容易:它们使用的目标文件不能太聪明。因此,创建代码描述的任务留给了人:头文件。
较新的语言完全绕过链接器(解释和VM语言)或使用自定义链接器(Turbo Pascal,我也假设Delphi)。即使是现在,当你处理链接器(或其较年轻的兄弟,动态库加载器)时,你需要对库中的内容进行某种描述。
答案 10 :(得分:0)
大多数其他语言并不像C ++那样难以解析和编译,因此分离标题和实现的“性能优化”并不那么重要。
答案 11 :(得分:0)
在C / C ++中,头文件基本上是一种对变量进行分组的方法,否则这些变量需要在每个使用它们的编译单元中声明为externs。
然而,这并没有限制C / C ++可以处理的问题域的复杂性或多样性。它只是编程语言的演变方式。最重要的是链接器以某种方式计算出你在程序中使用的所有变量的引用和类型。与新的编程语言相比,C / C ++这样做的方式相当粗糙,这些编程语言似乎具有处理变量和方法的外部引用的本地语言支持。