Al dividir su código en varios archivos, ¿qué debería ir exactamente en un archivo .hy qué debería ir en un archivo .cpp?
c++
header-files
Enrico Tuvera Jr
fuente
fuente
.hpp
archivo mientras que las declaraciones de C van en un.h
archivo. Esto es muy útil al mezclar código C y C ++ (por ejemplo, módulos heredados en C).Respuestas:
Los archivos de encabezado (
.h
) están diseñados para proporcionar la información que se necesitará en varios archivos. Cosas como declaraciones de clases, prototipos de funciones y enumeraciones suelen ir en archivos de encabezado. En una palabra, "definiciones".Los archivos de código (
.cpp
) están diseñados para proporcionar la información de implementación que solo debe conocerse en un archivo. En general, los cuerpos de las funciones y las variables internas a las que otros módulos nunca deben acceder, son lo que pertenecen a los.cpp
archivos. En una palabra, "implementaciones".La pregunta más simple que debe hacerse para determinar lo que pertenece a dónde es "si cambio esto, ¿tendré que cambiar el código en otros archivos para hacer que las cosas se compilen nuevamente?" Si la respuesta es "sí", probablemente pertenezca al archivo de encabezado; si la respuesta es "no", probablemente pertenezca al archivo de código.
fuente
export
). La única forma de evitar el n. ° 1 es PIMPL. # 2 sería posible siexport
fuera compatible y podría ser posible usando c ++ 0x yextern
plantillas. En mi opinión, los archivos de encabezado en c ++ pierden gran parte de su utilidad.El hecho es que, en C ++, esto es algo más complicado que la organización del encabezado / fuente de C.
¿Qué ve el compilador?
El compilador ve un archivo fuente grande (.cpp) con sus encabezados incluidos correctamente. El archivo fuente es la unidad de compilación que se compilará en un archivo objeto.
Entonces, ¿por qué son necesarios los encabezados?
Porque una unidad de compilación podría necesitar información sobre una implementación en otra unidad de compilación. Entonces, uno puede escribir, por ejemplo, la implementación de una función en una fuente y escribir la declaración de esta función en otra fuente que necesite usarla.
En este caso, hay dos copias de la misma información. Que es el mal ...
La solución es compartir algunos detalles. Si bien la implementación debe permanecer en la fuente, la declaración de símbolos compartidos, como funciones, o la definición de estructuras, clases, enumeraciones, etc., podría necesitar ser compartida.
Los encabezados se utilizan para poner esos detalles compartidos.
Mover al encabezado las declaraciones de lo que se debe compartir entre múltiples fuentes
¿Nada mas?
En C ++, hay algunas otras cosas que se podrían poner en el encabezado porque también necesitan ser compartidas:
Mueva al encabezado TODO lo que necesita ser compartido, incluidas las implementaciones compartidas
¿Significa entonces que podría haber fuentes dentro de los encabezados?
Si. De hecho, hay muchas cosas diferentes que podrían estar dentro de un "encabezado" (es decir, compartidas entre fuentes).
Se vuelve complicado, y en algunos casos (dependencias circulares entre símbolos), imposible mantenerlo en un encabezado.
Los encabezados se pueden dividir en tres partes
Esto significa que, en un caso extremo, podría tener:
Imaginemos que tenemos un MyObject con plantilla. Nosotros podríamos tener:
.
.
.
¡Guauu!
En la "vida real", suele ser menos complicado. La mayor parte del código tendrá solo una organización de fuente / encabezado simple, con algo de código en línea en la fuente.
Pero en otros casos (objetos con plantilla que se conocen entre sí), tenía que tener para cada objeto encabezados de declaración e implementación separados, con una fuente vacía que incluye esos encabezados solo para ayudarme a ver algunos errores de compilación.
Otra razón para dividir los encabezados en encabezados separados podría ser acelerar la compilación, limitando la cantidad de símbolos analizados a lo estrictamente necesario y evitando la recopilación innecesaria de una fuente que solo se preocupa por la declaración directa cuando cambia la implementación de un método en línea.
Conclusión
Debe hacer que la organización de su código sea lo más simple posible y lo más modular posible. Ponga tanto como sea posible en el archivo fuente. Solo exponga en los encabezados lo que debe compartirse.
Pero el día en que tenga dependencias circulares entre los objetos con plantilla, no se sorprenda si la organización de su código se vuelve algo más "interesante" que la organización simple de encabezado / fuente ...
^ _ ^
fuente
Además de todas las demás respuestas, le diré lo que NO coloca en un archivo de encabezado: la
using
declaración (el ser más comúnusing namespace std;
) no debe aparecer en un archivo de encabezado porque contaminan el espacio de nombres del archivo de origen en el que está incluido .fuente
using
para traer cosas al espacio de nombres global en un encabezado.static inline
en C99, debido a algo que tiene que ver con lo que sucede cuando se combinan vínculos internos con plantillas. Los espacios de nombres anon le permiten "ocultar" funciones, al tiempo que preservan el enlace externo.Lo que se compila en nada (huella binaria cero) va al archivo de encabezado.
Las variables no se compilan en nada, pero las declaraciones de tipos sí (porque solo describen cómo se comportan las variables).
las funciones no, pero las funciones en línea sí (o macros), porque producen código solo donde se llaman.
las plantillas no son código, son solo una receta para crear código. por lo que también van en archivos h.
fuente
En general, coloca declaraciones en el archivo de encabezado y definiciones en el archivo de implementación (.cpp). La excepción a esto son las plantillas, donde la definición también debe ir en el encabezado.
Esta pregunta y otras similares se han hecho con frecuencia en SO; consulte ¿Por qué tener archivos de encabezado y archivos .cpp en C ++? y archivos de encabezado C ++, separación de código, por ejemplo.
fuente
Las declaraciones de su clase y función más la documentación y las definiciones de funciones / métodos en línea (aunque algunos prefieren ponerlos en archivos .inl separados).
fuente
Principalmente, el archivo de encabezado contiene un esqueleto de clase o una declaración (no cambia con frecuencia)
y el archivo cpp contiene la implementación de la clase (cambia con frecuencia).
fuente
el archivo de encabezado (.h) debe ser para declaraciones de clases, estructuras y sus métodos, prototipos, etc. La implementación de esos objetos se realiza en cpp.
en .h
fuente
Esperaría ver:
Sin embargo, la respuesta real es qué no poner:
fuente
El encabezado Define algo pero no dice nada sobre la implementación. (Excluyendo Plantillas en esta "metafore".
Dicho esto, es necesario dividir las "definiciones" en subgrupos, en este caso, hay dos tipos de definiciones.
Ahora, por supuesto, estoy hablando del primer subgrupo.
El encabezado está ahí para definir el diseño de su estructura para ayudar al resto del software a usar la implementación. Es posible que desee verlo como una "abstracción" de su implementación, lo cual se dice vaughly, pero creo que se adapta bastante bien en este caso.
Como los carteles anteriores han dicho y mostrado, usted declara áreas de uso público y privado y sus encabezados, esto también incluye variables públicas y privadas. Ahora, no quiero entrar en el diseño del código aquí, pero es posible que desee considerar lo que coloca en sus encabezados, ya que esa es la capa entre el usuario final y la implementación.
fuente
fuente
Encabezado (.h)
Cuerpo (.cpp)
Como regla general, colocas la parte "compartida" del módulo en el .h (la parte que otros módulos deben poder ver) y la parte "no compartida" en el .cpp
PD: Sí, he incluido variables globales. Los he usado algunas veces y es importante no definirlos en los encabezados, o obtendrás muchos módulos, cada uno definiendo su propia variable.
EDITAR: Modificado después del comentario de David.
fuente