Combien de lignes de code sont dans le programme suivant?
#include <iostream>
int main()
{
std::cout << "Hello, world!\n";
return 0;
}
Vous avez probablement répondu 7 (ou 6 si vous n'avez pas compté la ligne vierge, ou 4 si vous n'avez pas compté les accolades).
Votre compilateur voit cependant quelque chose de très différent:
~$ cpp hello.cpp | wc
18736 40822 437015
Oui, c'est 18,7 KLOC juste pour un "Bonjour, monde!" programme. Le compilateur C ++ doit analyser tout cela. C'est une des principales raisons pour lesquelles la compilation C ++ prend si longtemps par rapport aux autres langages, et pourquoi les langages modernes évitent les fichiers d'en-tête.
Une meilleure question serait
Pourquoi ne C ++ ont des fichiers en- tête?
C ++ a été conçu pour être un surensemble de C, il devait donc conserver les fichiers d'en-tête pour une compatibilité descendante.
OK, alors pourquoi C a-t-il des fichiers d'en-tête?
En raison de son modèle de compilation séparé primitif. Les fichiers objets générés par les compilateurs C n'incluent aucune information de type, donc pour éviter les erreurs de type, vous devez inclure ces informations dans votre code source.
~$ 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
L'ajout des déclarations de type appropriées corrige le bogue:
~$ 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
Notez qu'il n'y a pas de par #include
. Mais lorsque vous utilisez un grand nombre de fonctions externes (ce que la plupart des programmes utiliseront), leur déclaration manuelle devient fastidieuse et sujette aux erreurs. Il est beaucoup plus facile d'utiliser des fichiers d'en-tête.
Comment les langues modernes peuvent-elles éviter les fichiers d'en-tête?
En utilisant un format de fichier objet différent qui inclut des informations de type. Par exemple, le format de fichier Java * .class comprend des "descripteurs" qui spécifient les types de champs et les paramètres de méthode.
Ce n'était pas une nouvelle invention. Plus tôt (1987), lorsque Borland a ajouté des «unités» compilées séparément à Turbo Pascal 4.0, il a choisi d'utiliser un nouveau *.TPU
format plutôt que Turbo C *.OBJ
afin de supprimer le besoin de fichiers d'en-tête.