Ile wierszy kodu znajduje się w następującym programie?
#include <iostream>
int main()
{
std::cout << "Hello, world!\n";
return 0;
}
Prawdopodobnie odpowiedziałeś 7 (lub 6, jeśli nie policzyłeś pustej linii lub 4, jeśli nie policzyłeś nawiasów klamrowych).
Twój kompilator widzi jednak coś zupełnie innego:
~$ cpp hello.cpp | wc
18736 40822 437015
Tak, to 18,7 KLOC tylko dla „Cześć, świecie!” program. Kompilator C ++ musi to wszystko przeanalizować . Jest to główny powód, dla którego kompilacja C ++ trwa tak długo w porównaniu z innymi językami i dlaczego współczesne języki unikają plików nagłówkowych.
Lepszym pytaniem byłoby
Dlaczego nie C ++ mają nagłówka pliki?
C ++ został zaprojektowany jako nadzbiór C, więc musiał zachować pliki nagłówkowe w celu zachowania kompatybilności wstecznej.
OK, więc dlaczego C ma pliki nagłówkowe?
Ze względu na jego pierwotny, osobny model kompilacji. Pliki obiektowe generowane przez kompilatory C nie zawierają żadnych informacji o typie, dlatego aby uniknąć błędów typu, należy uwzględnić te informacje w kodzie źródłowym.
~$ 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
Dodanie odpowiedniego typu deklaracji naprawia błąd:
~$ 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
Zauważ, że nie ma żadnych #include
. Ale gdy używasz dużej liczby funkcji zewnętrznych (co zrobi większość programów), ręczne ich deklarowanie staje się uciążliwe i podatne na błędy. Pliki nagłówkowe są znacznie łatwiejsze.
W jaki sposób nowoczesne języki są w stanie uniknąć plików nagłówkowych?
Przy użyciu innego formatu pliku obiektowego, który zawiera informacje o typie. Na przykład format pliku Java * .class obejmuje „deskryptory”, które określają typy pól i parametry metody.
To nie był nowy wynalazek. Wcześniej (1987), kiedy Borland dodał osobno skompilowane „jednostki” do Turbo Pascal 4.0, zdecydował się użyć nowego *.TPU
formatu zamiast Turbo C *.OBJ
, aby wyeliminować potrzebę plików nagłówkowych.