2008-12-02 9 views

Respuesta

28

Porque es una solución rápida, sucia y poco elegante para el problema de la interfaz frente a la implementación.

Se basa por completo en el preprocesador C, que es la herramienta más lúbrica del cajón.

Otras soluciones evitan los siguientes problemas:

  • dos archivos donde uno va a hacer
  • símbolos duplicado en conexión en tiempo debido a las múltiples definiciones
  • hinchazón de código debido a las múltiples 'estático' constantes
  • requisito para guardias de encabezado para evitar la inclusión múltiple
  • violación de los principios DRY
  • y más ...

Dviljoen cree que estoy siendo bastante duro con eso, y tiene razón. Es casi un 40-year old design, de la era de las tarjetas perforadas y la cinta de papel. Existe una increíble cantidad de software de alta calidad construido en C/C++ utilizando la disposición de archivos fuente/encabezado, a pesar de todos los posibles problemas y problemas encontrados anteriormente.

+0

Pero también permite algunas sutilezas, como decidir qué debe estar en la interfaz pública (las funciones en el archivo de encabezado) y cosas ocultas (por ejemplo, funciones estáticas en el archivo .c). – csl

+1

@csl: hay muchas formas mejores de lograr eso. Delphi tiene secciones de "implementación" e "interfaz" separadas dentro de un solo archivo, por ejemplo. – Roddy

+0

Si bien me gusta el encabezado/fuente de separación en C/C++, y no me gusta la visión de "una fuente" en Java, estoy de acuerdo con todo lo que dijo. +1 – paercebal

0

La mayoría de los otros lenguajes no son tan obtusos y difíciles de analizar y compilar como C++, por lo que la "optimización del rendimiento" de separar el encabezado y la implementación no es tan importante.

8

Porque significa duplicar información que puede obtener del código fuente. Otros idiomas intentan evitar esta duplicación de código.

En mis viejos días C, hice lo mismo. Mantuve toda la información en mis archivos .c y usé una pequeña herramienta para generar archivos de encabezado de ellos durante la compilación normal.

2

No son realmente necesarios en C# y Java, porque puede especificar el nivel de acceso para cada método (por ejemplo, público o privado), y además tiene reflectividad como no lo hace en C++.

Tenga en cuenta que para las prácticas no-OOP el uso de archivos de encabezado no es realmente tan malo. Por ejemplo, solo puede declarar qué funciones deben estar públicamente disponibles para los clientes en sus archivos de encabezado, mientras mantiene otras ocultas (y por lo tanto no accesibles) al declararlas únicamente en el archivo .cpp o .c.

6

En el caso de C#, los 3.0 specification estados

Debido a que un montaje es una unidad auto-descripción de la funcionalidad que contiene tanto el código y los metadatos, no hay necesidad de #include directivas y archivos de encabezado en C#. Los tipos y miembros públicos contenidos en un conjunto particular se hacen disponibles en un programa C# simplemente por haciendo referencia a ese ensamblado cuando compila el programa.

3

diría que, a ser posible, toda la información debe vivir en un solo lugar y tener un sistema de módulos que inteligentemente evitar una nueva compilación/importación de datos innecesarios y luego tener el compilador sea capaz de extraer la interfaz de sólo información si es necesario (p. ej., para enviar con una biblioteca o lo que sea).

5

Porque son restos del pasado.

El lenguaje moderno utiliza el concepto de módulos y paquetes.

Si desea utilizar una función/clase definida en otro archivo, importe ese archivo. El compilador determina los símbolos (es decir, los nombres) para que pueda usarlos.

El enfoque C/C++: es extraer las definiciones de funciones/clases a mano y ponerlas en otro archivo, luego hacer una inclusión de texto de esas definiciones en cualquier lugar que desee usarlas.

1

Para mí, los encabezados en C y C++ son un gran sumidero de tiempo y productividad. Compila ... Vaya, olvidé arreglar la firma de un método. Compilar ... whoops, necesita agregar el método a a la clase X.

1

Para deshacerse de los encabezados, la salida del compilador debe contener la descripción del código que el compilador puede comprender. Esto no fue fácil con los vinculadores más antiguos: los archivos objeto que consumieron no podían ser demasiado inteligentes. Por lo tanto, la tarea de crear la descripción del código se dejó a un ser humano: el archivo de encabezado.

Los idiomas más nuevos omiten el enlazador (los idiomas interpretados y VM) o usan enlazadores personalizados (Turbo Pascal, supongo Delphi también). Sin embargo, incluso ahora, cuando trabaje con el vinculador (o su hermano menor, el cargador dinámico de la biblioteca), debe producir algún tipo de descripción de lo que hay dentro de la biblioteca.

2

Yo diría que la mayoría de los lenguajes OO obtienen todo el kilometraje que necesitan en estas líneas de tener interfaces. Proporciona toda la flexibilidad (es decir, separación de la interfaz de la implementación) de los archivos de encabezado, a la vez que tiene contratos más estrictos con los clientes que usan las interfaces (porque el lenguaje/compilador los impone).

4

En C, no puede hacer referencias hacia adelante, es decir. use una función aún no definida antes de su uso. Los encabezados están hechos originalmente para eso, como referencias a la implementación.

Miré la respuesta aceptada de la pregunta a la que se hace referencia, y es correcta. Pero hoy en día, la velocidad de compilación es un problema menor (excepto, tal vez, con aplicaciones muy grandes: se necesita 1/4hr para compilar limpio la aplicación que tenemos, al menos en Windows). Y los detalles de la implementación están ocultos de todos modos, generalmente solo observamos la documentación de la API, es decir. la interfaz visible.

Para la anécdota, vi algunas librerías C++ implementadas al 99% en encabezados (solo con archivos .cpp donde el sistema los solicitaba), imitando así el estilo Java (C# no estaba aquí en ese momento ...).

0

En C/C++, los archivos de encabezado son básicamente una forma de agrupar variables que de otro modo tendrían que declararse como externas en cada unidad de compilación que se utilizan.

Sin embargo, eso no ha limitado la complejidad o la diversidad de los dominios problemáticos que C/C++ puede manejar. Es solo que el lenguaje de programación evolucionó de esa manera. Eventualmente, todo lo que importa es que el vinculador de alguna manera descubra todas las referencias y el tipo de variables que ha utilizado en su programa.

La manera en que C/C++ hace esto es bastante cruda en comparación con la nueva serie de lenguajes de programación que parecen tener soporte en el idioma nativo para manejar referencias externas a variables y métodos.

Cuestiones relacionadas