我发现头文件在浏览C ++源文件时很有用,因为它们给出了类中所有函数和数据成员的“摘要”。为什么这么多其他语言(例如Ruby,Python,Java等)没有这样的功能?这是C ++的详细信息派上用场的地方吗?
我发现头文件在浏览C ++源文件时很有用,因为它们给出了类中所有函数和数据成员的“摘要”。为什么这么多其他语言(例如Ruby,Python,Java等)没有这样的功能?这是C ++的详细信息派上用场的地方吗?
Answers:
头文件的最初目的是允许在C中进行单遍编译和模块化。通过在使用方法之前声明方法,它仅允许单遍编译。由于我们功能强大的计算机能够进行多次编译而没有任何问题,有时甚至比C ++编译器还要快,因此这个时代已经过去了。
C ++向后兼容C需要保留头文件,但在头文件上又添加了很多文件,这导致了相当麻烦的设计。FQA中的更多内容。
为了实现模块化,需要头文件作为有关模块中代码的元数据。例如。什么方法(和C ++类中)在哪个库中可用。让开发人员编写此代码很明显,因为编译时间很昂贵。如今,让编译器从代码本身生成此元数据已成为问题。Java和.NET语言通常会这样做。
所以不行。头文件不好。在那时,我们仍然必须在单独的软盘上使用编译器和链接器,并且编译花费了30分钟。如今,它们只是阻碍并且是不良设计的标志。
尽管它们作为文档形式可能对您有用,但围绕头文件的系统效率极低。
C语言的设计使每次编译过程都可以构建一个模块。每个源文件都是在编译器的单独运行中编译的。另一方面,对于引用它们的每个源文件,头文件都被注入到该编译步骤中。
这意味着,如果头文件包含在300个源文件中,则在构建程序时,头文件将被反复解析和编译300次。一遍又一遍完全相同的事物具有完全相同的结果。这是浪费大量的时间,并且是C和C ++程序花费如此长时间构建的主要原因之一。
所有现代语言都故意避免这种荒谬的低效率。取而代之的是,通常以编译语言将必需的元数据存储在生成输出中,从而使编译文件可以充当一种快速查找参考,以描述编译文件包含的内容。头文件的所有优点都是自动创建的,您无需进行任何其他工作。
交替使用解释语言,每个加载的模块都保留在内存中。引用或包括或要求某些库将读取并编译相关的源代码,该源代码将一直驻留在程序结束之前。如果您在其他地方也需要它,则因为已经加载,所以无需进行其他工作。
无论哪种情况,都可以使用该语言的工具“浏览”此步骤创建的数据。通常,IDE将具有某种类浏览器。而且,如果该语言具有REPL,它通常也可以用于生成任何已加载对象的文档摘要。
我一直很喜欢头文件,因为它们为实现提供了一种接口形式,以及一些额外的信息(例如类变量),它们都在一个易于查看的文件中。
我看到很多C#代码(每个类不需要2个文件)是每个类使用2个文件编写的-一个是实际的类实现,另一个是带有接口的。这种设计非常适合模拟(在某些系统中是必需的),并且有助于定义类的文档,而无需使用IDE来查看已编译的元数据。到目前为止,我会说它的良好做法。
因此,C / C ++强制在头文件中等效(多种)接口是一件好事。
我知道其他系统的支持者由于以下原因不喜欢它们:“如果必须将文件放入2个文件中,仅破解代码就更加困难”,但是我的态度是,仅破解代码并不是一种好习惯,一旦您开始编写/设计代码再想一想,那么您将理所当然地定义标题/接口。
我实际上会说头文件不是很好,因为它们使接口和实现变得混乱。一般而言,尤其是OOP编程的目的是拥有定义的接口并隐藏实现细节,但是C ++头文件向您显示方法,继承,公共成员(接口)以及私有方法和私有成员(实施的一部分)。更不用说在某些情况下,您最终会在头文件中内联代码或构造函数,并且某些库在头文件中包含模板代码,这实际上将实现与接口混合在一起。
我相信,其初衷是使代码可以使用其他库,对象等而不必导入脚本的全部内容。您只需要编译和链接的头文件即可。这样可以节省时间和周期。在那种情况下,这是一个不错的主意,但这只是解决这些问题的一种方法。
至于浏览程序的结构,大多数IDE都提供了该功能,并且有很多工具可以启动接口,进行代码分析,反编译等,因此您可以了解隐藏的内容。
至于为什么其他语言没有实现相同的功能?好吧,因为其他语言来自其他人,而这些设计师/创作者对事物的工作方式有不同的看法。
最好的答案是坚持做您需要做的工作,并使您感到快乐。
在许多编程语言中,当一个程序被细分为多个编译单元时,一个单元中的代码只有在编译器具有某种了解这些事物的方法的情况下,才能使用另一单元中定义的事物。而不是要求处理一个编译单元的编译器检查定义了当前单元中使用的任何内容的每个编译单元的整个文本,最好让编译器在处理每个单元时接收要编译的单元的全文。并从其他所有人那里得到一些信息。
在C语言中,程序员负责为每个单元创建两个文件-一个文件包含仅在编译该单元时需要的信息,另一个文件包含在编译其他单元时也需要的信息。这是一个很讨厌,很笨拙的设计,但是它避免了使用语言标准来指定有关编译器应如何生成和处理任何中间文件的任何要求。许多其他语言使用不同的方法,其中编译器将从每个源文件生成一个中间文件,该中间文件描述该源文件中所有可能由外部代码访问的内容。这种方法避免了在两个源文件中具有重复信息的需要,但是它要求编译平台以C不需要的方式定义文件语义。