2009-08-15 12 views
13

En un proyecto que tengo 2 clases:Circular C++ Header Incluye

// mainw.h

#include "IFr.h" 
... 
class mainw 
{ 
public: 
static IFr ifr; 
static CSize=100; 
... 
}; 

// IFr.h

#include "mainw.h" 
... 
class IFr 
{ 
public float[mainw::CSize]; 
}; 

Pero no puedo compilar este código, Obteniendo un error en la línea static IFr ifr;. ¿Está prohibido este tipo de inclusión cruzada?

+1

Supongo que debería ser mainw :: CSize –

Respuesta

15

Es este tipo de cruz -inclusiones están prohibidas?

Sí.

Una solución alternativa sería decir que el miembro de IFR de mainw es una referencia o un puntero, por lo que una visión de la declaración hará en lugar de incluir la declaración completa, como:

//#include "IFr.h" //not this 
class IFr; //this instead 
... 
class mainw 
{ 
public: 
static IFr* ifr; //pointer; don't forget to initialize this in mainw.cpp! 
static CSize=100; 
... 
} 

Alternativamente , defina el valor CSize en un archivo de encabezado separado (para que Ifr.h pueda incluir este otro archivo de encabezado en lugar de incluir mainw.h).

0

Si tienes

#ifndef __MYHEADER_NAME_WHICH_IS_RANDOM_PER_FILE_H 
#define __MYHEADER_NAME_WHICH_IS_RANDOM_PER_FILE_H 
//... Code.. 
#endif 

envuelto alrededor de su código, a continuación, que debe estar bien :)

[EDIT] Código de ortografía: O: P

+0

Eso no ayudaría en este caso. – ChrisW

+0

Esto realmente no ayudaría en este caso - debería ser obvio que la clase main claramente necesitaría ver la declaración completa de la clase Ifr antes de poder compilar –

+0

Ambos tienen razón. Supongo que fui un poco demasiado rápido en el gatillo :) – cwap

4

No puede tener dos clases que se incrustan entre sí de esta manera. Se podría hacer una de ellas un puntero:

class foo; 

class bar 
{ 
    foo* fooPtr; 
} 

Habría que construir foo y asignarlo a fooPtr en el constructor del bar y en el destructor - es sin duda un poco más de trabajo.

O, en este caso, como uno de los comentadores sugirió, haga mainw :: size a define y póngalo en algún lugar común.

1

Puede hacer recursivo incluye esto, pero en general también necesitará usar algún tipo de truco de protector de encabezado; de lo contrario, el preprocesador entrará en una recursión infinita. Esto no realmente le ayudará a resolver su problema de fondo, ya que básicamente tiene dos clases, cada una de ellas entre sí requieren para ver la declaración completa del otro con el fin de compilar:

class mainw 
{ 
public: 
static IFr ifr; // needs to see the full declaration of the Ifr class in order to know the size 
... 

class IFr 
{ 
public float[mainw::size]; // needs to see the full declaration of mainw in order to know what size is 

No importa que uno se pone primero, no podrá compilar porque necesita conocer todos los detalles del otro.

+0

Y dado que los detalles completos de la otra clase son necesarios para cada clase, una [declaración directa] (http://stackoverflow.com/q/553682/1497596) no ayuda. Sin embargo, si el archivo de inclusión para decir, clase 'A', contiene solo punteros o referencias a la clase' B', entonces una declaración directa a la clase 'B' dentro de la clase' A' puede hacer posible la compilación. – DavidRR

1

Ese tipo de inclusión circular no está permitido por C++, pero esto debería funcionar:

En lugar de incluir IFr.h, utilice una declaración hacia adelante.

class IFr; 
class mainw 
{ 
    //... 
}; 

Esto hará que mainw compilación muy bien, pero todo el código que utiliza el miembro ifr necesita incluir IFr.h también.

Esto solo funciona porque ifr es un miembro static. De lo contrario, el compilador necesitaría saber el tamaño exacto de ifr.

Además, como muchas otras personas han dicho, debería haber incluido protectores alrededor de ambos encabezados para evitar los errores que provienen de incluir el mismo encabezado dos veces.

#ifndef IFR_H 
#define IFR_H 
//... 
#endif 
1

Usted puede hacer:

// mainw.h 

#include "IFr.h" 
class mainw { 
public: 
    static const size_t CSize=100; 
    static IFr<CSize> ifr; 
... 
}; 

// IFr.h 
template <size_t Sz> 
struct IFr { 
    float sz_[Sz]; 
}; 

O en el caso CSIZE tiene que cambiar en tiempo de ejecución utiliza una solución de punta que @ChrisW encontró respuesta.