c++ - programa - Incluyendo#includes en el archivo de encabezado frente al archivo fuente
incluir un archivo c en otro (1)
En general, solo desea colocar las inclusiones mínimas necesarias en un archivo de encabezado de clase, ya que cualquier otra persona que use ese encabezado se verá obligada a #include
todas ellas también. En proyectos más grandes, esto conduce a construcciones más lentas, problemas de dependencia y todo tipo de otras maldades.
Piense en un archivo de encabezado como la interfaz pública para su clase. No desea ensillar a todos los que lo usan con dependencias adicionales, a menos que sean necesarios para poder usar la clase.
Mueva todo lo que sea necesario en la implementación de la clase al archivo fuente. Para otras clases utilizadas en un encabezado, solo #include
sus encabezados si realmente necesita saber su tamaño o contenido en el encabezado , cualquier otra cosa y una declaración de reenvío es suficiente. En la mayoría de los casos, solo necesita #include
clases de las que está heredando, y clases cuyos objetos son miembros de valor de su clase.
Esta página tiene un buen resumen. (Replicado a continuación para referencia)
El archivo de encabezado C ++ incluye patrones #
Los grandes proyectos de software requieren una administración cuidadosa de archivos de encabezado incluso cuando se programa en C. Cuando los desarrolladores se mueven a C ++, la administración de archivos de encabezado se vuelve aún más compleja y consume más tiempo. Aquí presentamos algunos patrones de inclusión de archivos de cabecera que simplificarán esta tarea.
Reglas de inclusión de archivos de encabezado
Aquí, discutimos las reglas básicas de inclusión de archivos de cabecera C ++ necesarios para simplificar la gestión de archivos de cabecera.
Un archivo de encabezado debe incluirse solo cuando una declaración directa no haga el trabajo. El archivo de encabezado debe diseñarse de modo que el orden de inclusión del archivo de encabezado no sea importante. Esto se logra asegurándose de que xh
sea el primer archivo de encabezado en x.cpp
El mecanismo de inclusión del archivo de encabezado debe ser tolerante para duplicar inclusiones de archivos de encabezado. Las siguientes secciones explicarán estas reglas con la ayuda de un ejemplo.
Ejemplo de inclusión del archivo de encabezado
El siguiente ejemplo ilustra diferentes tipos de dependencias. Supongamos una clase A con código almacenado en a.cpp
y ah
.
ah
#ifndef _a_h_included_
#define _a_h_included_
#include "abase.h"
#include "b.h"
// Forward Declarations
class C;
class D;
class A : public ABase
{
B m_b;
C *m_c;
D *m_d;
public:
void SetC(C *c);
C *GetC() const;
void ModifyD(D *d);
};
#endif
a.cpp
#include "a.h"
#include "d.h"
void A::SetC(C* c)
{
m_c = c;
}
C* A::GetC() const
{
return m_c;
}
void A::ModifyD(D* d)
{
d->SetX(0);
d->SetY(0);
m_d = d;
}
Análisis de inclusión de archivos
Analicemos las inclusiones del archivo de encabezado, desde el punto de vista de las clases involucradas en este ejemplo, es decir, ABase
, A
, B
, C
y D
- Clase ABase:
ABase
es la clase base, por lo que se requiere la declaración de clase para completar la declaración de clase. El compilador necesita conocer el tamaño deABase
para determinar el tamaño total deA
En este caso,abase.h
debe incluirse explícitamente enah
. - Clase B: la clase
A
contiene la claseB
por valor, por lo que se requiere la declaración de clase para completar la declaración de clase. El compilador necesita saber el tamaño de B para determinar el tamaño total deA
En este caso,bh
debe incluirse explícitamente enah
. - Clase C : la
Class C
se incluye solo como una referencia de puntero. El tamaño o el contenido real deC
no son importantes paraah
oa.cpp
. Por lo tanto, solo se ha incluido una declaración directa enah
. Tenga en cuenta quech
no se ha incluido ni enah
ni ena.cpp
. - Clase D : la clase
D
solo se utiliza como referencia de puntero enah
. Por lo tanto, una declaración directa es suficiente. Peroa.cpp
utiliza la claseD
en sustancia, por lo que explícitamente incluyedh
.
Puntos clave
Los archivos de encabezado deben incluirse solo cuando una declaración directa no hará el trabajo. Al no incluir ch
y dh
otros clientes de la clase A
nunca deben preocuparse por ch
y dh
menos que usen la clase C y D por valor. ah
se ha incluido como el primer archivo de encabezado en a.cpp
Esto se asegurará de que ah
no espere que se incluyan ciertos archivos de encabezado antes de ah
. Como ah
se ha incluido como el primer archivo, la compilación exitosa de a.cpp
garantizará que ah
no espere que se incluya ningún otro archivo de cabecera antes de ah
. Si esto se sigue para todas las clases (es decir, x.cpp
siempre incluye xh
como el primer encabezado) no habrá dependencia en la inclusión del archivo de encabezado. ah
incluye la verificación en la definición del preprocesador del símbolo _a_h_included_
. Esto lo hace tolerante a duplicar inclusiones de ah
.
Dependencia cíclica
Existe dependencia cíclica entre las clases X
e Y
en el siguiente ejemplo. Esta dependencia se maneja mediante el uso de declaraciones directas.
xh and yh
/* ====== x.h ====== */
// Forward declaration of Y for cyclic dependency
class Y;
class X
{
Y *m_y;
...
};
/* ====== y.h ====== */
// Forward declaration of X for cyclic dependency
class X;
class Y
{
X *m_x;
...
};
Me gusta poner todos mis #includes en mi archivo de encabezado y luego solo incluir mi encabezado para ese archivo fuente en mi archivo fuente. ¿Cuál es el estándar de la industria? ¿Hay algún inconveniente en mi método?