¿Debo poner las inclusiones en el archivo de encabezado o en el archivo de origen? Si el archivo de encabezado contiene las declaraciones de inclusión, si incluyo ese archivo de encabezado en mi fuente, ¿mi archivo de origen tendrá todos los archivos incluidos que estaban en mi encabezado? ¿O debería incluirlos solo en mi archivo fuente?
106
Respuestas:
Solo coloque inclusiones en un encabezado si el encabezado mismo los necesita.
Ejemplos:
size_t
. Luego#include <stddef.h>
en el archivo de encabezado .strlen
. Luego#include <string.h>
en el archivo fuente .fuente
size_t
?size_t
ostd::string
?Ha habido bastante desacuerdo sobre esto a lo largo de los años. En un momento, era tradicional que un encabezado solo declarara lo que estaba en cualquier módulo con el que estaba relacionado, por lo que muchos encabezados tenían requisitos específicos que le
#include
permitían un cierto conjunto de encabezados (en un orden específico). Algunos programadores de C extremadamente tradicionales todavía siguen este modelo (religiosamente, al menos en algunos casos).Más recientemente, ha habido un movimiento para hacer que la mayoría de los encabezados sean independientes. Si ese encabezado requiere algo más, el encabezado mismo se encarga de eso, asegurándose de que se incluya todo lo que necesite (en el orden correcto, si hay problemas de pedido). Personalmente, prefiero esto, especialmente cuando el orden de los encabezados puede ser importante, resuelve el problema una vez, en lugar de requerir que todos los que lo usan resuelvan el problema una vez más.
Tenga en cuenta que la mayoría de los encabezados solo deben contener declaraciones. Esto significa que agregar un encabezado innecesario no debería (normalmente) tener ningún efecto en su ejecutable final. Lo peor que pasa es que ralentiza un poco la compilación.
fuente
Sus correos
#include
electrónicos deben ser archivos de encabezado, y cada archivo (fuente o encabezado) debe tener#include
los archivos de encabezado que necesita. Los archivos de encabezado deben tener#include
los archivos de encabezado mínimos necesarios, y los archivos de origen también deben, aunque no es tan importante para los archivos de origen.El archivo de origen tendrá los encabezados
#include
, y los encabezados#include
, y así sucesivamente hasta la profundidad máxima de anidamiento. Esta es la razón por la que no desea mensajes de correo#include
electrónico superfluos en los archivos de encabezado: pueden hacer que un archivo de origen incluya muchos archivos de encabezado que puede que no necesite, lo que ralentiza la compilación.Esto significa que es muy posible que los archivos de encabezado se incluyan dos veces y eso puede ser un problema. El método tradicional es poner "incluir guardias" en los archivos de encabezado, como este para el archivo foo.h:
fuente
El enfoque en el que he evolucionado durante más de veinte años es este;
Considere una biblioteca.
Hay varios archivos C, un archivo H interno y un archivo H externo. Los archivos C incluyen el archivo H interno. El archivo H interno incluye el archivo H externo.
Verá que desde el punto de vista de los compiladores, a medida que compila un archivo C, hay una jerarquía;
externo -> interno -> código C
Este es el orden correcto, ya que lo externo es todo lo que un tercero necesita para usar la biblioteca. Lo que es interno es necesario para compilar el código C.
fuente
Si un archivo de cabecera
#includes
archivos de cabecera B y C, entonces cada archivo de origen que#includes
A será también obtener B y C#included
. El preprocesador, literalmente, simplemente realiza la sustitución de texto: en cualquier lugar donde encuentre texto que dice que#include <foo.h>
lo reemplaza con el texto delfoo.h
archivo.Hay diferentes opiniones sobre si debe colocar
#includes
encabezados o archivos fuente. Personalmente, prefiero poner todo#includes
en el archivo de origen de forma predeterminada, pero cualquier archivo de encabezado que no se pueda compilar sin otros encabezados de requisitos previos debe#include
incluir esos encabezados.Y cada archivo de encabezado debe contener una protección de inclusión para evitar que se incluya varias veces.
fuente
En algunos entornos, la compilación será más rápida si solo se incluyen los archivos de encabezado que se necesitan. En otros entornos, la compilación se optimizará si todos los archivos de origen pueden usar la misma colección primaria de encabezados (algunos archivos pueden tener encabezados adicionales más allá del subconjunto común). Idealmente, los encabezados deben construirse para que múltiples operaciones #include no tengan ningún efecto. Puede ser bueno rodear las declaraciones #include con comprobaciones de la protección de inclusión del archivo a incluir, aunque eso crea una dependencia en el formato de esa protección. Además, dependiendo del comportamiento de almacenamiento en caché de archivos de un sistema, un #include innecesario cuyo objetivo termine siendo completamente # ifdef'ed away puede no tardar mucho.
Otra cosa a considerar es que si una función toma un puntero a una estructura, se puede escribir el prototipo como
sin una definición de BAR_s que tenga que estar dentro del alcance. Un enfoque muy útil para evitar inclusiones innecesarias.
PD: en muchos de mis proyectos, habrá un archivo que se espera que cada módulo #incluya, que contiene cosas como typedefs para tamaños enteros y algunas estructuras y uniones comunes [p. Ej.
(Sí, sé que tendría problemas si me cambiara a una arquitectura big-endian, pero dado que mi compilador no permite estructuras anónimas en uniones, el uso de identificadores con nombre para los bytes dentro de la unión requeriría que se acceda a ellos como theUnion.b.b1 etc.que parece bastante molesto.
fuente
Cree todos sus archivos para que se puedan construir utilizando solo lo que incluyen. Si no necesita una inclusión en su encabezado, elimínela. En un gran proyecto, si no mantiene esta disciplina, se deja abierto a romper una compilación completa cuando alguien elimina una inclusión de un archivo de encabezado que está siendo utilizado por un consumidor de ese archivo y ni siquiera por el encabezado.
fuente
Su archivo fuente tendrá las declaraciones de inclusión si las coloca en el encabezado. Sin embargo, en algunos casos sería mejor ponerlos en el archivo fuente.
Recuerde que si incluye ese encabezado en cualquier otra fuente, también obtendrán las inclusiones del encabezado, y eso no siempre es deseable. Solo debe incluir cosas donde se use.
fuente
Solo debe incluir archivos en su encabezado que necesite para declarar constantes y declaraciones de funciones. Técnicamente, estas inclusiones también se incluirán en su archivo fuente, pero en aras de la claridad, solo debe incluir en cada archivo los archivos que realmente necesita usar. También debe protegerlos en su encabezado de la inclusión múltiple de la siguiente manera:
Esto evita que el encabezado se incluya varias veces, lo que da como resultado un error del compilador.
fuente