Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I have a homework assignment and I need to evaluate which approach is better according to GRASP "Protected Variation". I found a question on Stack Overflow about the separation of header and code files in C++.

However, what I want to know why Java does not follow C++ in promoting the separation between class definitions and class implementations. Are there any advantages with the Java method, over the C++ method?

share|improve this question
    
If you want to ask "Why doesn't Java use header files", then just ask that and do away with the "which is better" stuff - as you've seen, we're allergic to that ;) Also search, I'm pretty certain this (or at least closely related questions) have been brought up before. –  delnan Nov 8 '11 at 17:09
    
oops, the link didn't work. I'll reformulate, what I wanted to know basically, is the differences between both of them and which one tends to be more easy to reuse the code or for extensibility. –  CoachNono Nov 8 '11 at 17:11
1  
C (and by extension C++) really had no choice but to separate the header files from the implementation files, due to the limited one-pass compiler technology at the time C was created. –  Channel72 Nov 8 '11 at 17:11
2  
Java can have Interfaces which can separate class definition and class implementation, if the class in question implements the interface. Not quite the same as C++ though. –  FrustratedWithFormsDesigner Nov 8 '11 at 17:22
1  
Also, C++ header files expose considerably more implementation than I like, unless you use the PIMPL idiom. It's necessary to list all the data members, even if private, so the implementation will know the size, and the private member functions also. –  David Thornley Nov 8 '11 at 17:31
show 4 more comments

5 Answers

up vote 12 down vote accepted

How many lines of code are in the following program?

#include <iostream>

int main()
{
   std::cout << "Hello, world!\n";
   return 0;
}

You probably answered 7 (or 6 if you didn't count the blank line, or 4 if you didn't count the braces).

Your compiler, however, sees something very different:

~$ cpp hello.cpp | wc
  18736   40822  437015

Yes, that's 18.7 KLOC just for a "Hello, world!" program. The C++ compiler has to parse all that. This is a major reason why C++ compilation takes so long compared to other languages, and why modern languages eschew header files.

A better question would be

Why does C++ have header files?

C++ was designed to be a superset of C, so it had to keep header files for backwards compatibility.

OK, so why does C have header files?

Because of its primitive separate compilation model. The object files generated by C compilers don't include any type information, so in order to prevent type errors you need to include this information in your source code.

~$ cat sqrtdemo.c 
int main(void)
{
    /* implicit declaration int sqrt(int) */
    double sqrt2 = sqrt(2);
    printf("%f\n", sqrt2);
    return 0;
}

~$ gcc -Wall -ansi -lm -Dsqrt= sqrtdemo.c
sqrtdemo.c: In function ‘main’:
sqrtdemo.c:5:5: warning: implicit declaration of function ‘printf’ [-Wimplicit-function-declaration]
sqrtdemo.c:5:5: warning: incompatible implicit declaration of built-in function ‘printf’ [enabled by default]
~$ ./a.out 
2.000000

Adding the proper type declarations fixes the bug:

~$ cat sqrtdemo.c 
#undef printf
#undef sqrt

int printf(const char*, ...);
double sqrt(double);

int main(void)
{
    double sqrt2 = sqrt(2);
    printf("%f\n", sqrt2);
    return 0;
}

~$ gcc -Wall -ansi -lm sqrtdemo.c
~$ ./a.out 
1.414214

Notice that there are no #includes. But when you use a large number of external functions (which most programs will), manually declaring them gets tedious and error-prone. It's much easier to use header files.

How are modern languages able to avoid header files?

By using a different object file format that includes type information. For example, the Java *.class file format includes "descriptors" that specify the types of fields and method parameters.

This was not a new invention. Earlier (1987), when Borland added separately-compiled "units" to Turbo Pascal 4.0, it chose to use a new *.TPU format rather than Turbo C's *.OBJ in order to remove the need for header files.

share|improve this answer
    
Although interestingly, I'm fairly sure that you could set Turbo Pascal to output OBJ files rather than TPUs... –  Michael Kjörling Nov 9 '11 at 12:33
add comment

Java has interfaces to define a contract. This gives a higher level of abstraction from what the caller needs and the actual implementation. i.e. the caller doesn't need to know the implementing class, it only needs to know the contract it supports.

Say you want to write a method which slows all the key/values in a Map.

public static <K,V> void printMap(Map<K,V> map) {
    for(Entry<K,V> entry: map.entrySet())
        System.out.println(entry);
}

This method can call entrySet() on an abstract interface which is removed from the class implementing it. You can call this method with.

printMap(new TreeMap());
printMap(new LinkedHashMap());
printMap(new ConcurrentHashMap());
printMap(new ConcurrentSkipListMap());
share|improve this answer
1  
Welcome to Programmers there Peter - thought I recognized the name :-). I'll add that some people will argue that Abstract base classes in Java also define a contract - but that's probably an argument for a separate thread. –  Martijn Verburg Nov 8 '11 at 22:26
    
Hello @MartijnVerburg, Nice addition. I think abstract classes blur the distinction between interfaces without implementations and concrete classes. Extension methods will blur the distinction even further. I tend to prefer to use an interface if I can as they are simpler. –  Peter Lawrey Nov 8 '11 at 22:39
    
Yeah Java is going to start heading down the Scala path of having multiple ways to define a public contract - I'm not sure that's a good thing or not yet :-) –  Martijn Verburg Nov 9 '11 at 9:26
    
-1 This is possible in C++ as well, with a simple #define interface class. –  Sjoerd Nov 9 '11 at 13:06
    
@Sjoerd I didn't know C++ methods no longer need to use the virtual keyword to get polymorphism and this has no performance penalty if you only use one or two concrete types, like they are in Java. Can you point me to any documentation on how this works in C++? –  Peter Lawrey Nov 9 '11 at 13:56
add comment

Headers exist, quite frankly, as a historical accident. It's an incredibly poor system, no other language has anything so terrible, and anyone who doesn't have to deal with them should rejoice.

share|improve this answer
add comment

Headers are there to enable separate compilation. By #including the headers, the compiler doesn't need to know anything about the binary structure of compiled C++ code, and can leave that job to a separate linker. Java does not use a separate linker with its compiler, and since .class files are strictly defined, the compiler is able to read them to determine all their members with all their types, without any need to re-declare them in each compilation unit.

You can include all the implementation in a C++ header, but it causes the compiler to recompile it every time it's #included, forcing the linker to sort out and discard the duplicate copies.

share|improve this answer
add comment

Java does promote the separation of class definition and implementation, it just depends where you're looking from.

When you're the author of a Java class you get to see the definition of the class as well as its implementation in one file. This simplifies the development process as you've only gor to go to one place to maintain the class, you don't have to switch between two files (.h and .cpp as you would in C++). However, when you're the consumer of the class you only deal with the definition, via a .class file that is either packaged in a .jar or a standalone .class

C++ allows you to separate the definition and implementation, but it's ad-hoc. For example, there's nothing to stop you writing the method inline within the header file, and for template classes this is mandatory. The header file also lists out any member variables, which are visible to anyone who looks at the header file, even though they're an implementation detail of the class and irrelevant to a consumer.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.