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 #include
s. 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.
private
, so the implementation will know the size, and theprivate
member functions also.