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:
ABasees 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 deABasepara determinar el tamaño total deAEn este caso,abase.hdebe incluirse explícitamente enah. - Clase B: la clase
Acontiene la claseBpor 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 deAEn este caso,bhdebe incluirse explícitamente enah. - Clase C : la
Class Cse incluye solo como una referencia de puntero. El tamaño o el contenido real deCno son importantes paraahoa.cpp. Por lo tanto, solo se ha incluido una declaración directa enah. Tenga en cuenta quechno se ha incluido ni enahni ena.cpp. - Clase D : la clase
Dsolo se utiliza como referencia de puntero enah. Por lo tanto, una declaración directa es suficiente. Peroa.cpputiliza la claseDen 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?