Java vs C++ – Separation of Class Definitions and Implementations

cjavaprogramming-languages

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?

Best Answer

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.