简体   繁体   English

仅使用头文件进行编程?

[英]Programming with just header files?

If a header file is just a piece of code that gets pasted onto another when I use #include then what is stopping me from programming in C using only .h files? 如果头文件只是一段代码,当我使用#include时会粘贴到另一个代码上,那么是什么使我无法仅使用.h文件在C语言中进行编程? You can even #include into other header files! 您甚至可以#include到其他头文件中!

I assume there must be some performance or workflow reason why this isn't more common, but if it exists I do not know what it is. 我认为一定有一些性能或工作流程的原因使这种情况不常见,但如果存在,我不知道它是什么。

Therefore my question is: What is the reason people don't program entire applications with just header files? 因此,我的问题是: 人们为什么不只使用头文件来编写整个应用程序的原因什么?

Header files come with the concept of modularisation, ie of separating the source code of a large program into several independent parts, ie translation units. 头文件带有模块化的概念,即将大型程序的源代码分成几个独立的部分,即翻译单元。 Thereby, implementation details are hidden to other translation units, and dependencies are dramatically reduced. 由此,实现细节对其他翻译单元隐藏,并且依赖性大大降低。 But: if a translation unit A needs to call a function from another translation B, it needs to have the function prototype of the respective function, ie the function without the body - something like int functionFromB(int x); 但是:如果翻译单元A需要从另一个翻译B调用函数,则它需要具有相应函数的函数原型,即没有主体的函数-类似于int functionFromB(int x); in order to tell the compiler how to call it. 为了告诉编译器如何调用它。 So translation unit A could simple write this prototype at the beginning; 因此,翻译部门A可以在开始时简单地编写此原型。 but usually functions from translation unit B (eg B.cpp) are exposed in a header file Bh , which comprises all the "public" functions of B in form of function prototypes. 但是通常来自转换单元B的功能(例如B.cpp)在头文件Bh中公开,头文件Bh以功能原型的形式包含B的所有“公共”功能。 Same applies to type definitions and (global) variables. 同样适用于类型定义和(全局)变量。 Then A simply can include Bh in order to have all the function prototypes et al. 然后,A可以简单地包含Bh ,以具有所有功能原型等。 available without the necessity of knowing all the implementation details (like the function bodies). 无需了解所有实现细节(如功能主体)就可以使用。

So you can write a large program completely in .h -files; 因此,您可以完全在.h -files中编写大型程序; yet you have to tell the compiler to treat them as translation units (usually only .cpp -files are treated as such), and you still have to provide function prototypes et al... 但是您必须告诉编译器将它们视为翻译单元(通常仅将.cpp -files视为此类),并且您仍然必须提供函数原型等。

With translation units, you have separate / independent modules. 使用翻译单元,您可以拥有独立的模块。 This is in contrast to a large monolithic block, which you get when you "paste" all the chunks of your program spread over different .h -files by #include -ing them "together". 这是相对于一个大的整块,当你“粘贴”所有程序分布在不同的块,你得到.h -files通过#include -ing他们“在一起”。 You can compile / test / distribute translation units separately, whereas a monolithic block cannot be compiled / tested / distributed partly. 您可以分别编译/测试/分发翻译单元,而整体块不能部分编译/测试/分发。

Header files are a necessity of C and C++ when you need to reference code or data structures across different files, something especially important when external programs that need to link against a library and the compiler has to understand how to use it. 当您需要引用不同文件中的代码或数据结构时,头文件是C和C ++的必需品,当需要链接到库的外部程序和编译器必须了解如何使用它时,头文件尤其重要。

It's advantageous to break up your application into a series of .c or .cpp files in order to make the compilation process more efficient. 将您的应用程序分解为一系列.c.cpp文件,以使编译过程更有效是有利的。 Most compiler environments, where they're Makefile driven or IDE managed, have methods for detecting which files need to be recompiled when a change is made. 大多数由Makefile驱动或IDE管理的编译器环境都具有检测更改时需要重新编译哪些文件的方法。

In larger applications building all files can take considerable time, but recompiling a single .cpp file is often fairly quick. 在较大的应用程序中,构建所有文件可能需要花费大量时间,但是重新编译单个.cpp文件通常非常快。 So long as you change only the .cpp source and don't touch the headers you can do a quick recompile and relink, ready for testing right away. 只要仅更改.cpp源,并且不触及标题,就可以进行快速重新编译和重新链接,以准备立即进行测试。

If instead you put everything into a header file then you'd need to recompile everything, every time, which can be a painfully slow process. 相反,如果将所有内容都放入头文件中,那么您每次都需要重新编译所有内容,这可能是一个非常缓慢的过程。

Keep in mind some code bases can take hours to rebuild, so this is not a sustainable practice. 请记住,某些代码库可能需要数小时才能重建,因此这不是可持续的做法。

I thought of a strange analogy. 我想到了一个奇怪的比喻。

You go to a restaurant. 你去餐厅
The waiter presents you with a menu. 服务员为您提供菜单。 The menu is your interface to the kitchen. 菜单是您进入厨房的界面。
You pick the dish(es) you want to order. 您选择要点的菜。

Then, 然后,

Option 1: 选项1:

The waiter asks you to move to the kitchen and see for yourself how the dishes are prepared. 服务员请您搬到厨房,亲自看看如何准备菜肴。 You remain in the kitchen until the food is served to you. 您待在厨房里直到食物送达为止。

Option 2: 选项2:

The waiter brings the food to your table after it is prepared in a kitchen that you don't necessarily see. 在您不一定要看到的厨房里准备好食物后,服务员将食物带到您的餐桌上。

Which one would you prefer? 您想要哪一个?

Putting the implementation in the .h file is analogous to Option 1. 将实现放入.h文件类似于选项1。

Putting the implementation in a .c/.cpp file somewhere else is analogous to Option 2. 将实现放在.c / .cpp文件中的其他位置类似于选项2。

Header files are different from source files by convention. 根据惯例,头文件与源文件不同。 Using the .h or .hpp extension communicates that the file is intended to be #included and is not meant to exist as a standalone source file. 使用.h.hpp扩展名表示该文件应包含在#included ,而不是作为独立的源文件存在。 You can generally assume that .h / .hpp files are safe to include from multiple source files. 通常,您可以假定.h / .hpp文件可以安全地包含在多个源文件中。

Meanwhile, .c and .cpp extensions communicate that the file likely is intended to be a translation unit and is not suitable to be #included in other translation units. 同时, .c.cpp扩展名表明该文件可能旨在用作翻译单元,而不适合#included在其他翻译单元中。

You could very well write an entire codebase with every file having any arbitrary extension, or none at all, if you really want to make it hard on yourself and anybody else working in the codebase. 如果您真的想让自己和其他在代码库中工作的人感到困难,那么您可以编写一个完整的代码库,每个文件都具有任意扩展名,或者根本没有扩展名。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM