I find header files to be useful when browsing C++ source files, because they give a “summary” of all the functions and data members in a class. Why do so many other languages (like Ruby, Python, Java, etc.) not have a feature like this? Is this an area where C++’s verbosity comes in handy?
2
Original purpose of header files was to allow single-pass compilation and modularity in C. By declaring the methods before they are used, it allowed for only single compilation pass. This age is long time gone thanks to our powerfull computers being able to do multi-pass compilation without any problems, and sometimes even faster than C++ compilers.
C++ being backwards compatible with C needed to keep the header files, but added lot of on top of them, which resulted in quite problematic design. More in FQA.
For modularity, header files were needed as metadata about code in modules. Eg. what methods (and in C++ classes) are available in what library. It was obvious to have developer write this, because compile time was expensive. Nowadays, it is no problem to have compiler generate this metadata from code itself. Java and .NET languages do this normally.
So no. Header files are not good. They were when we still had to have compiler and linker on separate floppies and compilation took 30 minutes. Nowadays, they only get in the way and are sign of bad design.
14
While they may be useful for you as a form of documentation, the system surrounding header files is extraordinarily inefficient.
C was designed so that each compilation pass builds a single module; each source file is compiled in a separate run of the compiler. Header files, on the other hand, are injected into that compilation step for each of the source files that reference them.
This means that if your header file is included in 300 source files, then it gets parsed and compiled over and over, 300 separate times while your program is built. The exact same thing with the exact same result, over and over. This is a huge waste of time, and is one of the primary reasons why C and C++ programs take so long to build.
All modern languages intentionally avoid this absurd little inefficiency. Instead, typically in compiled languages the necessary metadata is stored within the build output, allowing the compiled file to act as a sort of quick-lookup reference describing what the compiled file contains. All the benefits of a header file, automatically created with no additional work on your part.
Alternately in interpreted languages, every module that gets loaded stays in memory. Referencing or including or requiring some library will read and compile the associated source code, which stays resident until the program ends. If you also require it elsewhere, no additional work as it’s already been loaded.
In either case, you can “browse” the data created by this step using the language’s tools. Typically the IDE will have a class browser of some sort. And if the language has a REPL, it can also often be used to generate a documentation summary of any loaded objects.
1
It is not clear on, what you mean by browsing file for functions and data members. However, most IDE’s do provide Tools to browse the class and see class data members.
For example: Visual Studio has Class View
and Object browser
that nicely provides your requested functionality. Like in the following screen-shots.
An additional disadvantage of header files is that the program depends on the order of their inclusion, and the programmer has to take extra steps to ensure correctness.
That, coupled with C’s macro system (inherited by C++), leads to many pitfalls and confusing situations.
To illustrate, if one header defined some symbol using macros for its use, and another header used the symbol in another fashion such as a name for a function, then the order of inclusion would greatly influence the final result. There are many such examples.
I always liked header files as they provide a form of interface to the implementation, along with some extra information such as class variables, all in one easy-to-view file.
I see a lot of C# code (that doesn’t need 2 files per class) written using 2 files per class – one the actual class implementation, and another with an interface in it. This design is good for mocking (essential in some systems) and helps to define the documentation of the class without having to use the IDE to view the compiled metadata. I’d go so far to say its good practice.
So C/C++ mandating an equivalent (of sorts) of an interface in header files is a good thing.
I know there are proponents of other systems that do not like them for reasons including ‘its more difficult to just hack out code if you have to put things in 2 files’, but my attitude is that just hacking out code is not good practice anyway, and once you start writing/designing code with a bit more thought, then you’ll be defining headers/interfaces as a matter of course.
5
I would actually say that headers files are not great because they muddy the interface and implementation. The intent with programming in general, and especially OOP is to have a defined interface and hide the implementation details, but a C++ header file shows you both the methods, inheritance, and the public members (interface) as well as private methods and private members (some part of the implementation). Not to mention that in some cases you end up inlining code or constructors in the header file, and some libraries include template code in the headers, which really mixes implementation with interface.
The original intent, I believe, was to make it possible for code to use other libraries, objects, etc without having to import the entire contents of the script. All you need is the header to compile and link. It saves time and cycles that way. In that instance, it’s a decent idea, but it’s just one way of solving these issues.
As for browsing the structure of the program, most IDEs provide that ability, and there are a lot of tools that will kick out the interfaces, do code analysis, decompilation, etc so you can see what’s happening under the covers.
As for why other languages don’t implement the same feature? Well, because other languages come from other people, and those designers/creators have a different vision of how things should work.
The best answer is to stick with what does the job you need to do, and makes you happy.
In many programming languages, when a program is subdivided into multiple compilation units, code in one unit will only be able to use things defined in another if the compiler has some means of knowing what those things are. Rather than requiring that a compiler processing one compilation unit examine the entire text of every compilation unit which defines anything used within the present unit, it’s best to have the compiler receive, while processing each unit, the full text of the unit to be compiled along with a little information from all of the others.
In C, the programmer is responsible for creating two files for each unit–one containing information which will only be needed when compiling that unit, and one containing information which will also be needed when compiling other units. This is a rather nasty, hacky, design, but it avoids the need to have a language standard specify anything about how compilers should generate and process any intermediate files. Many other languages use a different approach, wherein a compiler will generate from each source file an intermediate file describing everything in that source file which is supposed to be accessible to outside code. This approach avoids the need to have duplicate information in two source files, but it requires that a compilation platform have defined file semantics in a way that is not required for C.