views:

1819

answers:

16

Many languages, such as Java, C#, do not separate declaration from implementation. C# has a concept of partial class, but implementation and declaration still remain in the same file.

Why doesn't C++ have the same model? Is it more practical to have header files?

I am referring to current and upcoming versions of C++ standard.

+34  A: 

Backwards Compatibility - Header files are not eliminated because it would break Backwards Compatibility.

Gavin Miller
+1 - the only reason that is significant enough to continue putting up with header files :/
romkyns
+25  A: 

Header files allow for independent compilation. You don't need to access or even have the implementation files to compile a file. This can make for easier distributed builds.

This also allows SDKs to be done a little easier. You can provide just the headers and some libraries. There are, of course, ways around this which other languages use.

Steve Rowe
Clearly ease is not a reason for headers, as: (1) they are difficult to maintain, they are duplicate code, and (2) for a SDK, they can be automatedly extracted. Distributed builds I suppose is a correct point.
You could easily do independent compilation without header files.
Bill K
I would argue that C++ headers DO NOT separate implementation from interface. In order to get true separation you have to use PIMPL or somesuch abstract.
KitsuneYMG
Although *in theory* you're correct -- if the header files are light and only declare the interface -- in practice, header files are heavy and laden with conditional compilation items.
Randolpho
Headers enable separate compilation and SDKs in a rather primitive way, but they aren't required to support these things - .NET and Java support both without using headers.
Michael Burr
@Michael, isn't that what I said?
Steve Rowe
amen thats it...
ojblass
The worst part about C++ headers is that they expose private information - which is needed so that code using the class can know how much space to reserve if the class is allocated on the stack.
kyoryu
+28  A: 

I routinely flip between C# and C++, and the lack of header files in C# is one of my biggest pet peeves. I can look at a header file and learn all I need to know about a class - what it's member functions are called, their calling syntax, etc - without having to wade through pages of the code that implements the class.

And yes, I know about partial classes and #regions, but it's not the same. Partial classes actually make the problem worse, because a class definition is spread across several files. As far as #regions go, they never seem to be expanded in the manner I'd like for what I'm doing at the moment, so I have to spend time expanding those little plus's until I get the view right.

Perhaps if Visual Studio's intellisense worked better for C++, I wouldn't have a compelling reason to have to refer to .h files so often, but even in VS2008, C++'s intellisense can't touch C#'s

Marc Bernier
You are doing the machine's job of extracting documentation, and _liking_ it. Wow...
In Java/C# you use Interfaces to show the api. This is a MUCH better way of showing the API than a header file. A separate class file is used as an implementation.
KitsuneYMG
kts, well you normally don't have interfaces for everything. A lot of the API is in concrete classes. You normally show the API with a dedicated doc extraction tool, either one generating HTML or one embedded in the IDE (Object Explorer in VS)
I'm torn between liking and not liking header files. I like them becaus like you, I like having one succinct place to go for the details I need. Also, no machine is going to extract the information from source code as well as a human can type it into a header file. OTOH, it is duplicate code.
Dunk
Quote: "in VS2008, C++'s intellisense can't touch C#'s". Yes, it isnt a failing in the language it is because Microsoft try to kill anything that isn't Microsoft. IE: anti-competitive.
Brock Woolf
The limitation of VS' intellisense was due to it being derived from from their command line C++ compiler via ifdefs. This is being corrected, and intellisense for c++ is supposed to greatly improve in VS10: http://blogs.msdn.com/vcblog/archive/2009/01/27/dev10-is-just-the-beginning.asp
luke
Back when I started C, I preferred having header files for the exact same reason. As I became more accustomed to development, however, I found myself checking the man pages more and more frequently because it wasn't always obvious what certain parameters were for. Now days, I use the MSDN.
senfo
I agree with Marc. Header files are a great place to store basic documentation; the next level of detail is the man page/MSDN. I do not particularly have my productivity improved by wading through code.
Paul Nathan
@Iraimbilanja, I can't say that I like it, just that it's better than the alternative. Ideally the stinkin' intellisense would work properly. I could perhaps understand for my own code why it can't, but it can't even do Windows API functions sometimes. Why MS? Why?
Marc Bernier
+1, because I share the same dev process.
paercebal
YES BUT... without walking the extra mile, C++ header files mix implementaton details and public contract.
peterchen
@kts: I know using interfaces as pseudo-headers is common, but I think it's a really terrible pattern, personally.
kyoryu
Let's see you use the headers to check out the interface of std::vector... or any other std collection class... or absolutely anything at all in boost... All of those are completely useless for this purpose.
romkyns
If you use header files to look at a class’s members, then you haven’t learnt to use Visual Studio properly. Try taking a look at the Navigation Bar, or the Class View, or the Object Explorer. If that isn’t enough, you can always write your own tools that process the XML documentation files generated by the compiler. C#’s facilities for browsing classes is so vastly superior to C++’s I can’t even begin to find the words for it.
Timwi
@luke, yes its a lil bit better, though it seems like this imrovement came with a price - no IntelliSense at all for C++/Cli anymore..
smerlin
+4  A: 

C was made to make writing a compiler easily. It does a LOT of stuff based on that one principle. Pointers only exist to make writing a compiler easier, as do header files. Many of the things carried over to C++ are based on compatibility with these features implemented to make compiler writing easier.

It's a good idea actually. When C was created, C and Unix were kind of a pair. C ported Unix, Unix ran C. In this way, C and Unix could quickly spread from platform to platform whereas an OS based on assembly had to be completely re-written to be ported.

The concept of specifying an interface in one file and the implementation in another isn't a bad idea at all, but that's not what C header files are. They are simply a way to limit the number of passes a compiler has to make through your source code and allow some limited abstraction of the contract between files so they can communicate.

These items, pointers, header files, etc... don't really offer any advantage over another system. By putting more effort into the compiler, you can compile a reference object as easily as a pointer to the exact same object code. This is what C++ does now.

C is a great, simple language. It had a very limited feature set, and you could write a compiler without much effort. Porting it is generally trivial! I'm not trying to say it's a bad language or anything, it's just that C's primary goals when it was created may leave remnants in the language that are more or less unnecessary now, but are going to be kept around for compatibility.


It seems like some people don't really believe that C was written to port Unix, so here: (from)

The first version of UNIX was written in assembler language, but Thompson's intention was that it would be written in a high-level language.

Thompson first tried in 1971 to use Fortran on the PDP-7, but gave up after the first day. Then he wrote a very simple language he called B, which he got going on the PDP-7. It worked, but there were problems. First, because the implementation was interpreted, it was always going to be slow. Second, the basic notions of B, which was based on the word-oriented BCPL, just were not right for a byte-oriented machine like the new PDP-11.

Ritchie used the PDP-11 to add types to B, which for a while was called NB for "New B," and then he started to write a compiler for it. "So that the first phase of C was really these two phases in short succession of, first, some language changes from B, really, adding the type structure without too much change in the syntax; and doing the compiler," Ritchie said.

"The second phase was slower," he said of rewriting UNIX in C. Thompson started in the summer of 1972 but had two problems: figuring out how to run the basic co-routines, that is, how to switch control from one process to another; and the difficulty in getting the proper data structure, since the original version of C did not have structures.

"The combination of the things caused Ken to give up over the summer," Ritchie said. "Over the year, I added structures and probably made the compiler code somewhat better -- better code -- and so over the next summer, that was when we made the concerted effort and actually did redo the whole operating system in C."


Here is a perfect example of what I mean. From the comments:

Pointers only exist to make writing a compiler easier? No. Pointers exist because they're the simplest possible abstraction over the idea of indirection. – Adam Rosenfield (an hour ago)

You are right. In order to implement indirection, pointers are the simplest possible abstraction to implement. In no way are they the simplest possible to comprehend or use. Arrays are much easier.

The problem? To implement arrays as efficiently as pointers you have to pretty much add a HUGE pile of code to your compiler.

There is no reason they couldn't have designed C without pointers, but with code like this:

int i=0;
while(src[++i])
    dest[i]=src[i];

it will take a lot of effort (on the compilers part) to factor out the explicit i+src and i+dest additions and make it create the same code that this would make:

while(*(dest++) = *(src++))
    ;

Factoring out that variable "i" after the fact is HARD. New compilers can do it, but back then it just wasn't possible, and the OS running on that crappy hardware needed little optimizations like that.

Now few systems need that kind of optimization (I work on one of the slowest platforms around--cable set-top boxes, and most of our stuff is in Java) and in the rare case where you might need it, the new C compilers should be smart enough to make that kind of conversion on its own.

Bill K
Pointers only exist to make writing a compiler easier? No. Pointers exist because they're the simplest possible abstraction over the idea of indirection.
Adam Rosenfield
Pascal was made to make writing a compiler easy. You can pretty much get away with a simple hand-coded recursive-descent parser. C is more complicated.
David Thornley
Anyone who says that writing a C compiler is simple has never written a C compiler.
anon
@Adam being the simplest abstraction is only beneficial for implementation. There is no benefit if a better abstraction can put out the same code.
Bill K
David Thornley
@David How does the fact that Pascal might be easier have any impact on C? Look at the wikipedia entry for C under philosophy. It's goals are all consistent with porting to other systems. Also, look at tiny-c, a trivial to understand yet completely usable implementation (last time I checked).
Bill K
@David there are other ways just as clear that translate into the exact same code, but harder to optimize. To optimize an array to the level of a pointer is some seriously annoying code.
Bill K
Contrary to what you believe, nobody is arguing that the idea behind C wasn't to rewrite Unix in. However, pointers were not to make it easier to compile C, and it isn't clear that header files were either.
David Thornley
David Thornley
anon
@David At the time I believe Pascal was interpreted--something they tried and quickly threw out. Plus it did not have constructs to replace those in C efficiently. It was not a very good compiler for porting itself and Unix which is what I'm saying the main goal was.
Bill K
How could I use that array syntax to read the four bytes out of memory-mapped IO address 0x8000A000? Or to store and pass around multiple references to the same location in heap without making a global array base? How would I kick off a DMA? Get an address to pass to a SIMD intrinsic?
Crashworks
@crashworks Are you absolutely certain that it's completely impossible to come up with some type of syntax that might allow you to set the base address of an array?
Bill K
Well, of course one could dochar AllTheMemory[] ; AllTheMemory = 0x00;int ReadFromIOPort=AllTheMemory[0x8000A000];but then you're just back at pointers only with a roundabout syntax.
Crashworks
Correct, The choice of syntax was driven by simpler compiler design. You see the syntax you are used to as "Normal" and arrays roundabout, but nearly every other language not concerned with optimizing output code has chosen arrays.
Bill K
Also with an array you could specify size and never have an NPE, but again, almost impossible to optimize without a runtime component (which itself was impossible for the time). C was, dare I say, a virtually PERFECT solution for the problems it needed to solve (Porting itself and an OS).
Bill K
@Bill K: The first Pascal implementation I'm aware of was the compiler for Control Data computers. The first one that was really popular on small computers was the UCSD system, which was interpreted in precisely the same way Java is: both were/are compiled, and then run on a virtual machine. By the way, Pascal does have real pointers. However, my point always has been that C was not designed for ease of compilation, and I was comparing to Pascal as a language of similar vintage that was.
David Thornley
@David Thornley C was designed to port Unix. Needed to be a compiler that was easy to port. Needed to be a language that was easy to optimize. Quotes in the question regarding the creation process. Creating a usable, readable general purpose language was never a goal. What are you actually questioning? Can you show any references?
Bill K
+8  A: 

One of C++'s goals is to be a superset of C, and it's difficult for it to do so if it cannot support header files. And, by extension, if you wish to excise header files you may as well consider excising CPP (the pre-processor, not plus-plus) altogether; both C# and Java do not specify macro pre-processors with their standards (but it should be noted in some cases they can be and even are used even with these languages).

As C++ is designed right now, you need prototypes -- just as in C -- to statically check any compiled code that references external functions and classes. Without header files, you would have to type out these class definitions and function declarations prior to using them. For C++ not to use header files, you'd have to add a feature in the language that would support something like Java's import keyword. That'd be a major addition, and change; to answer your question of if it'd be practical: I don't think so--not at all.

Peter
+8  A: 

If you want C++ without header files then I have good news for you.

It already exists and is called D (http://www.digitalmars.com/d/index.html)

Technically D seems to be a lot nicer than C++ but it is just not mainstream enough for use in many applications at the moment.

James Dean
The key point with D, whether you use it or not, is that it has most of C++'s feature set. You might have argued that C++ needs header files because templates need them, or because you somehow need them where efficient code is concerned. Both of these are shown to be false by D's existence.
quark
+16  A: 

Even Bjarne Stroustrup has called header files a kludge.

But without a standard binary format which includes the necessary metadata (like Java class files, or .Net PE files) I don't see any way to implement the feature. A stripped ELF or a.out binary doesn't have much of the information you would need to extract. And I don't think that the information is ever stored in Windows XCOFF files.

Max Lybbert
I'd take Mr. Stroustrup more seriously if he had invented the header files. Then he'd be admitting his mistake rather than badmouthing the language he pointedly made it a goal to remain backwards-compatible with. It's like deciding to make an octopus and then complaining about how many tentacles you have to put on it.
Chris Lutz
I'd take Mr. Stroustrup more seriously if he could write a compiler. Than he could put whatever information he wanted into the object files, regardless of format or stripping.
kmarsh
C++ headers are ugly. In well-written C code, headers are great - private implementation details in a source file are *truly* private, and are not exposed at all, to anybody.
kyoryu
I'd take Mr. Stroustrup more seriously if he had *gotten rid* of header files.
quark
@Chris Lutz, Kmarsh, Quark. You're talking (incredibly ignorantly) about a man who developed C++ before most of you were born.
10ToedSloth
+2  A: 

If you want the reason why this will never happen: it would break pretty much all existing C++ software. If you look at some of the C++ committee design documentation, they looked at various alternatives to see how much code it would break.

It would be far easier to change the switch statement into something halfway intelligent. That would break only a little code. It's still not going to happen.

EDITED FOR NEW IDEA:

The difference between C++ and Java that makes C++ header files necessary is that C++ objects are not necessarily pointers. In Java, all class instances are referred to by pointer, although it doesn't look that way. C++ has objects allocated on the heap and the stack. This means C++ needs a way of knowing how big an object will be, and where the data members are in memory.

David Thornley
C++ needing a way to know the class layout in memory doesn't mean that it necessarily needs header files. Header files are the current mechanism by which C++ acquires that information, not the only possible mechanism.
andref
+1  A: 

Well, C++ per se shouldn't eliminate header files because of backwards compatibility. However, I do think they're a silly idea in general. If you want to distribute a closed-source lib, this information can be extracted automatically. If you want to understand how to use a class w/o looking at the implementation, that's what documentation generators are for, and they do a heck of a lot better a job.

dsimcha
A: 

No language exists without header files. It's a myth.

Look at any proprietary library distribution for Java (I have no C# experience to speak of, but I'd expect it's the same). They don't give you the complete source file; they just give you a file with every method's implementation blanked ({} or {return null;} or the like) and everything they can get away with hiding hidden. You can't call that anything but a header.

There is no technical reason, however, why a C or C++ compiler could count everything in an appropriately-marked file as extern unless that file is being compiled directly. However, the costs for compilation would be immense because neither C nor C++ is fast to parse, and that's a very important consideration. Any more complex method of melding headers and source would quickly encounter technical issues like the need for the compiler to know an object's layout.

coppro
The Java compiler extracts that information from the .class files. Not only that: the Sun JDK came with the source code for most of the classes (except those in com.sun.*).
andref
+7  A: 

In The Design and Evolution of C++, Stroustrup gives out one more reason...

The same header file can have two or more implementation files which can be simultaneously worked-upon by more than one programmer without the need of a source-control system.

This might seem odd these days, but I guess it was an important issue when C++ was invented.

Abhay
Even with a source-control system, working on separate files sure simplifies merges.
kmarsh
+1 for *The same header file can have two or more implementation files*. That is a godsend for doing a portable application without abusing `#ifdef`-fu. (Just use a makefile that generate the correct `myclass.o` from the plateform-dependent `myclass-win.cpp` / `myclass-linux.cpp`, and the outside just cares about `myclass.h`)
Steve Schnepp
Good point Steve.
Abhay
A: 

Oh Yes!

After coding in Java and C# it's really annoying to have 2 files for every classes. So I was thinking how can I merge them without breaking existing code.

In fact, it's really easy. Just put the definition (implementation) inside an #ifdef section and add a define on the compiler command line to compile that file. That's it.

Here is an example:

/* File ClassA.cpp */

#ifndef _ClassA_
#define _ClassA_

#include "ClassB.cpp"
#include "InterfaceC.cpp"

class ClassA : public InterfaceC
{
public:
    ClassA(void);
    virtual ~ClassA(void);

    virtual void methodC();

private:
    ClassB b;
};

#endif

#ifdef compiling_ClassA

ClassA::ClassA(void)
{
}

ClassA::~ClassA(void)
{
}

void ClassA::methodC()
{
}

#endif

On the command line, compile that file with

-D compiling_ClassA

The other files that need to include ClassA can just do

#include "ClassA.cpp"

Of course the addition of the define on the command line can easily be added with a macro expansion (Visual Studio compiler) or with an automatic variables (gnu make) and using the same nomenclature for the define name.

Vincent
+1  A: 

There is value in defining the class interface in a separate component to the implementation file.

It can be done with interfaces, but if you go down that road, then you are implicitly saying that classes are deficient in terms of separating implementation from contract.

Modula 2 had the right idea, definition modules and implementation modules. http://www.modula2.org/reference/modules.php

Java/C#'s answer is an implicit implementation of the same (albeit object-oriented.)

Header files are a kludge, because header files express implementation detail (such as private variables.)

In moving over to Java and C#, I find that if a language requires IDE support for development (such that public class interfaces are navigable in class browsers), then this is maybe a statement that the code doesn't stand on its own merits as being particularly readable.

I find the mix of interface with implementation detail quite horrendous.

Crucially, the lack of ability to document the public class signature in a concise well-commented file independent of implementation indicates to me that the language design is written for convenience of authorship, rather convenience of maintenance. Well I'm rambling about Java and C# now.

polyglot
+3  A: 

Many people are aware of shortcomings of header files and there are ideas to introduce more powerful module system to C++. You might want to take a look at Modules in C++ (Revision 5) by Daveed Vandevoorde.

Piotr Dobrogost
Unfortunately, it didn't make it to C++0x and was postponed to a future TR.
andref
+3  A: 

One advantage of this separation is that it is easy to view only the interface, without requiring an advanced editor.

Dimitri C.
A: 

Still I don't get the point of some statements. Separation of API and implementation is a very good thing, but header files are not API. There are private fields there. If you add or remove private field you change implementation and not API.

qax