2009-10-02 14 views
6

No entiendo muy bien el punto de tener un encabezado; ¡parece violar el principio DRY! Toda la información en un encabezado está (puede estar) contenida en la implementación.¿Cuál es el razonamiento detrás de los encabezados?

+1

¿Quiere decir archivos de encabezado, como en un proyecto C? – timdev

+0

Correcto. (15 caracteres) – RCIX

+3

tienes razón. Lo que estás olvidando es que fueron inventados hace más de 30 años. Debes comprometerte para obtener algo que sea lo suficientemente simple de compilar en unos pocos KB de memoria. – jalf

Respuesta

20

Simplifica el proceso de compilación. Cuando desee compilar unidades de forma independiente, necesita algo para describir las partes a las que se vinculará sin tener que importar la totalidad de todos los demás archivos.

También permite la ocultación de código. Uno puede distribuir un encabezado para permitir que otros usen la funcionalidad sin tener que distribuir la implementación.

Finalmente, puede alentar la separación de la interfaz de la implementación.

No son la única forma de resolver estos problemas, pero hace 30 años eran buenos. Probablemente no usaríamos archivos de cabecera para un idioma hoy, pero no fueron inventados en 2009.

+0

Pero si no distribuye la implementación, ¿cómo funcionan sus llamadas? mágicamente se extiende a través de Internet para llamar a su copia? – RCIX

+11

Envías código de biblioteca compilado + encabezados. – timdev

+0

Entonces, ¿cómo cosas como .NET o tal permiten la exploración API de archivos DLL compilados? – RCIX

0

¿Y si le quiere dar a alguien más las declaraciones para usar su biblioteca sin darles la implementación?

Como otra respuesta señala: la razón original de los encabezados era facilitar el análisis/compilación en las plataformas con herramientas muy simples y limitadas. Fue un gran paso adelante tener una máquina con 2 disquetes para que tuvieras el compilador en una y tu código en la otra, lo que hizo las cosas mucho más fáciles.

+0

Podría imaginar un compilador que tendría la opción de tomar sus archivos de origen y generar archivos de declaración automáticamente ... no es necesario que los mantenga usted mismo. –

+0

Sí, podría hacerlo, pero necesitaría una forma de decirle qué debería exportarse y qué no. Escribir sus propios encabezados le permite ser muy específico. – dmckee

3

Ayuda a pensar un poco sobre las capacidades de las computadoras que estaban disponibles cuando, digamos c, se escribió. La memoria principal se midió en kilovatios, y no necesariamente en muchos de ellos. Los discos eran más grandes, pero no mucho. Almacenamiento en serio significaba cintas de carrete, montadas a mano, por operadores malhumorados, que realmente querían que te marcharas para poder jugar a cazar al wumpus. Una máquina de 1 MIPS era gritando rápido. Y con todas estas limitaciones tenía que compartir. Posiblemente con un puntaje de otros usuarios.

Cualquier cosa que redujo el espacio o complejidad del tiempo de compilación fue una gran victoria. Y los encabezados hacen ambas cosas.

+4

"Operadores gruñones" no jugaron a cazar al wumpus. Estábamos perdidos en un laberinto de pasajes revirados, todos por igual. – themis

4

Los arquitectos de muchos lenguajes modernos como Java, Eiffel y C# están claramente de acuerdo con usted: esos lenguajes extraen los metadatos sobre un módulo de la implementación. Sin embargo, per se, el concepto de encabezados no excluye eso: obviamente, sería una tarea simple para un compilador extraer un archivo .h al compilar un .c, por ejemplo, al igual que los compiladores para esos otros lenguajes lo hacen implícitamente. El hecho de que los compiladores típicos actuales de C no lo hagan no es un problema de diseño de lenguaje; es un problema de implementación; aparentemente, los usuarios no demandan esa característica, por lo que ningún proveedor de compiladores se molesta en implementarla.

Como opción de diseño de idioma, tener archivos .h separados (en un formato de texto editable y legible por humanos) le ofrece lo mejor de ambos mundos: puede comenzar compilando código de cliente por separado en una implementación de módulo que aún no existir, si lo desea, escribiendo el archivo .h a mano; o usted (suponiendo por absurdo una implementación del compilador que lo suministra ;-) puede obtener el archivo .h automáticamente desde la implementación como un efecto secundario de compilarlo.

Si C, C++, & c, sigan prosperando (al parecer todavía lo están haciendo bien hoy ;-), y la demanda como la suya para no escribir manualmente crece, eventualmente los compiladores tendrán que proporcionar la "generación de encabezado" opción, y "lo mejor de ambos mundos" no será teórico!-)

+2

¿Cómo es lo mejor de ambos mundos tener que mantener la misma información en dos archivos? Lo mejor de ambos mundos sería tener algo así como archivos de encabezado generados de forma automática e implícita para la conveniencia del programador. Los encabezados son un truco primitivo que requiere una tonelada de esfuerzo extra, ralentizando la compilación (en las bases de códigos de hoy en las CPU actuales) y complicando su código al obligarlo a pensar en la inclusión y en el orden de las declaraciones para evitar referencias cíclicas. Y los compiladores no pueden simplemente definir automáticamente el archivo .h. Alteraría la semántica de su código en algunos casos. – jalf

+2

@jaif, como dije, nada en el compilador _forbids_ de los compiladores estándar C tiene una bandera para generar opcionalmente .h desde .c en la compilación (incluidas todas las entidades visibles externamente y aquellas solamente): si piensas lo contrario, muéstrame dónde está prohibido . Si los compiladores NO LO HACEN en la práctica, tiene que ser por falta de demanda, es decir, los usuarios de C o C++ claramente no creen que la falta de esta característica sea un gran problema, de lo contrario presionarían a los proveedores de compiladores para que no lo hagan. ¡ofrecelo! –

1

No tienes encabezados en Java, pero tienes interfaces y todos los gurús de Java importantes recomiendan que definas cualquier cosa que otros proyectos/sistemas utilicen como interfaz y como implementación.

Veamos una definición de interfaz java que contiene firmas de llamada, definiciones de tipo y contants.

Los archivos de encabezado MOST C contienen firmas de llamada, definiciones de tipos y constantes.

Por lo tanto, para todos los fines prácticos, los archivos de encabezado C/C++ son solo definiciones de interfaz y, por lo tanto, deben considerarse una buena cosa. Ahora sé que es posible definir una miríada de otras cosas en los archivos de cabecera, así (MARCROs, constantes, etc, etc), pero que sólo una parte de todo el maravilloso mundo de C: -

int function target() { 
    // Default for shoot 
    return FOOT; 
} 
+0

Puede que no lo haya notado, pero Java no requiere que # incluya una definición de interfaz antes de que pueda usarla. Los encabezados sí. ¿Eso los hace una buena cosa? – jalf

+0

Sí, pero las interfaces tienen un propósito específico: garantizar que pueda acceder a * algunas * propiedades y llamar * a algunos métodos en una clase de objetos sin saber realmente qué objeto es específicamente. Los encabezados existen únicamente como una repetición del contenido de un único archivo (Objective-) C (++), solo en forma condensada (al menos como se ha visto). – RCIX

1

para el detalle Leer this

Un archivo de encabezado comúnmente contiene declaraciones directas de clases, subrutinas, variables y otros identificadores. Los programadores que desean declarar identificadores estandarizados en más de un archivo fuente pueden colocar dichos identificadores en un único archivo de encabezado, que otro código puede incluir siempre que se requiera el contenido del encabezado.

La biblioteca estándar C y la biblioteca estándar C++ declaran tradicionalmente sus funciones estándar en archivos de encabezado.

+0

Buen punto, supongo. – RCIX

2

La idea de inspeccionar los archivos de salida binarios de los procesadores de lenguaje hubiera sido difícil de comprender cuando C inventó los archivos .h. Había un sistema llamado JOVIAL que hacía algo parecido, pero era exótico y se limitaba más o menos exclusivamente a proyectos militares. (Nunca he visto un programa JOVIAL, solo he oído hablar de él.)

De modo que cuando salió C, el patrón de diseño habitual para la modularidad fue "sin controles". Puede haber una restricción de que los símbolos .text solo puedan enlazar con .text y .data a .data, pero eso fue todo. Es decir, los compiladores del día típicamente procesaban un archivo fuente a la vez y luego los enlazadores los juntaban sin el más mínimo nivel de comprobación de errores, salvo que, si tuviera suerte, "Soy un símbolo de función" frente a "Soy un símbolo de datos ".

De modo que la idea de que el compilador realmente entendiera que lo que llamaba era algo nuevo.

Incluso hoy, si haces un encabezado totalmente falso, nadie te atrapa en la mayoría de AOT compilers. Cosas inteligentes como los lenguajes CLR y Java realmente codifican cosas en los archivos de la clase.

Así que sí, a la larga, probablemente no tengamos archivos de encabezado.

2

No olvide la documentación que proporciona un encabezado. Por lo general, hay algo que necesita saber para usar el módulo. Yo, por mi parte, no quiero escanear un código fuente demasiado extenso para saber qué necesito usar y cómo llamarlo ... De todos modos, extraería esta información, lo que efectivamente da como resultado un archivo de encabezado. Ya no es un problema con los IDEs modernos, por supuesto, pero trabajando con un viejo código C Me encanta tener archivos de encabezado hechos a mano que incluyen comentarios sobre el uso y sobre las pre y postcondiciones.

fuente Keeping, cabecera y documentación adicional en sincronía todavía es otra lata de gusanos ...

0

Al dividir el código en archivos de cabecera y de la fuente se divide declaración y definición.Cuando mira en los archivos de encabezado, puede ver lo que tiene y si va a ver los detalles de implementación, vaya al archivo de origen.

Cuestiones relacionadas