2011-02-08 18 views
5

He estado buscando en el SDK de Miedo para mi proyecto de la universidad, pero han notado un cierto código de este modo:¿Por qué incluir un encabezado y reenviar declarar la clase contenida en el mismo archivo cpp?

foo.h

class Foo 
{ 
    public: 
     int iSomething; 
}; 

Bar.cpp:

#include "Foo.h" 

// Forward declarations 
class Foo; 

Es ¿Hay alguna razón particular para reenviar declarar Y incluir el encabezado apropiado en el mismo archivo cpp? ¿O es la declaración directa redundante porque se está incluyendo el encabezado?

EDIT:

Cada vez que he visto en el código, la instrucción de inclusión es siempre antes de la declaración hacia adelante.

Respuesta

6

Es más que simplemente redundante, es potencialmente problemático. Say Foo.h cambia para que Foo se convierta en un tipo dede cierta instanciación particular de un equivalente genérico, templado - el tipo de cosa que se puede anticipar como parte de la evolución normal del software. Luego de Bar.cpp "clase X" será innecesariamente causar un ala error de compilación:

--- fwd.h --- 
template <typename T> 
class XT 
{ 
    public: 
    int n_; 
}; 

typedef XT<int> X; 

--- fwd.cc --- 
#include "fwd.h" 

class X; 

int main() 
{ 
    X x; 
    x.n_ = 0; 
    return x.n_; 
} 

--- compilation attempt --- 
~/dev .../gcc/4.1.1/exec/bin/g++ fwd.cc -o fwd 
fwd.cc:3: error: using typedef-name 'X' after 'class' 
fwd.h:8: error: 'X' has a previous declaration here 

Ésta es una razón por la que siempre recomiendo usar dedicado cabeceras prospectivas de declaración ala <iosfwd>, mantenido con e incluidos por la cabecera principal para asegurar curso consistencia. Nunca puse "clase X"; en un archivo de implementación a menos que la clase esté definida allí también. Recuerde que los aparentes beneficios de la "clase X"; las declaraciones de reenvío no son tanto que eviten un #include, y más que los archivos que incluyen pueden ser grandes y, a su vez, incluir muchos otros archivos: los encabezados de declaración avanzada suelen evitar la abrumadora mayoría de eso de todos modos.

1

La declaración directa es redundante, pero también bastante inofensiva. Tal vez el autor usa muchas declaraciones avanzadas y no garantiza rigurosamente que siempre sean necesarias.

3

Si la declaración directa llegó antes que las inclusiones, podría eliminar una dependencia. Venir después del archivo .h real que lo define no hace nada.

+0

¿Puedes elaborar? Originalmente escribí exactamente lo mismo, pero luego pensé un poco más sobre eso y pensé que si Bar forward-declara Foo, inmediatamente # incluye a Foo.h, debería a) siempre dar como resultado la declaración de Foo de todos modos, yb) nunca dependas de otro encabezado que ya haya declarado a Foo. ¿Puedes dar un ejemplo de por qué tener la declaración directa antes del #include realmente ayuda? – mgiuca

+0

@mgiuca - reduce los tiempos de compilación. muchas veces el código solo usa punteros, y nunca requiere el tamaño real de la clase [y nunca crea instancias].En esas circunstancias, basta con una declaración hacia adelante, lo que le ahorra el tiempo de incluir otros archivos. –

+0

@Foo Bah Sí, es una buena razón para usar una declaración directa * en lugar de * a #include. Pero eso no explica por qué tendrías ambos. Si tuviera ambas cosas, necesitaría procesar el archivo incluido, ya sea que se haya utilizado o no. – mgiuca

2

El original class Foo; puede haber sido vestigial.

Recuerde que, si la fuente solo utiliza punteros a la clase Foo [y no intenta crear objetos Foo o punteros Foo de desreferencia], no necesita definir la clase antes de usarla.

Sin ver el código, me gustaría tratar de adivinar que la versión original de bar.cpp tenía código que no requiere la definición de foo

utilizo hacia adelante declaraciones en grandes proyectos para reducir el tiempo de compilación. el tiempo de compilación no es un problema cuando demora un segundo, pero cuando los proyectos tardan una hora en generar cada segundo ayuda :)

Cuestiones relacionadas