¿Cuántas líneas de código hay en el siguiente programa?
#include <iostream>
int main()
{
std::cout << "Hello, world!\n";
return 0;
}
Probablemente respondió 7 (o 6 si no contó la línea en blanco, o 4 si no contó las llaves).
Sin embargo, su compilador ve algo muy diferente:
~$ cpp hello.cpp | wc
18736 40822 437015
Sí, eso es 18.7 KLOC solo por un "¡Hola, mundo!" programa. El compilador de C ++ tiene que analizar todo eso. Esta es una razón importante por la que la compilación de C ++ tarda tanto en comparación con otros lenguajes, y por qué los lenguajes modernos evitan los archivos de encabezado.
Una mejor pregunta sería
¿ Por qué C ++ tiene archivos de encabezado?
C ++ fue diseñado para ser un superconjunto de C, por lo que tenía que mantener los archivos de encabezado para la compatibilidad con versiones anteriores.
Bien, entonces ¿por qué C tiene archivos de encabezado?
Debido a su primitivo modelo de compilación por separado. Los archivos de objetos generados por los compiladores de C no incluyen ningún tipo de información, por lo que para evitar errores de tipo, debe incluir esta información en su código fuente.
~$ 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
Agregar las declaraciones de tipo adecuadas corrige el error:
~$ 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
Tenga en cuenta que no hay #include
s. Pero cuando usa una gran cantidad de funciones externas (que la mayoría de los programas usarán), declararlas manualmente se vuelve tedioso y propenso a errores. Es mucho más fácil usar archivos de encabezado.
¿Cómo pueden los idiomas modernos evitar los archivos de encabezado?
Mediante el uso de un formato de archivo de objeto diferente que incluye información de tipo. Por ejemplo, el formato de archivo Java * .class incluye "descriptores" que especifican los tipos de campos y parámetros de métodos.
Este no fue un invento nuevo. Anteriormente (1987), cuando Borland agregó "unidades" compiladas por separado a Turbo Pascal 4.0, eligió usar un nuevo *.TPU
formato en lugar de Turbo C *.OBJ
para eliminar la necesidad de archivos de encabezado.