2009-08-15 11 views
13

In un progetto che ho 2 classi:Circolare C++ intestazione include

// 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]; 
}; 

Ma non riesco a compilare questo codice, ottenendo un errore sulla linea static IFr ifr;. È proibito questo tipo di cross-inclusion?

+1

Suppongo che dovrebbe essere mainw :: CSize –

risposta

15

è questo tipo di croce -inclusioni sono proibite?

Sì.

A aggirare sarebbe a dire che l'elemento IFR di mainw è un riferimento o un puntatore, in modo che un attaccante dichiarazione farà invece di includere la dichiarazione completa, come:

//#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 , definire il valore CSize in un file di intestazione separato (in modo che Ifr.h possa includere questo altro file di intestazione invece di includere mainw.h).

0

Se hai

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

avvolto intorno al vostro codice, allora si dovrebbe andare bene :)

[EDIT] Codice ortografia: O: P

+0

Ciò non sarebbe di aiuto in questo caso. – ChrisW

+0

Questo non sarebbe di grande aiuto in questo caso - dovrebbe essere ovvio che la classe mainw avrebbe chiaramente bisogno di vedere la dichiarazione completa della classe Ifr prima che potesse compilare –

+0

Avete entrambi ragione. Suppongo di essere un po 'troppo veloce sul grilletto :) – cwap

4

Non è possibile avere due classi che si incorporano in questo modo. Si potrebbe fare uno di loro un puntatore:

class foo; 

class bar 
{ 
    foo* fooPtr; 
} 

Dovresti costruire foo e assegnarlo a fooPtr nel costruttore di bar e la connessione nel distruttore - è sicuramente un po 'più di lavoro.

Oppure, in questo caso, come suggerito da uno dei commentatori, rendere mainw :: size a define e metterlo da qualche parte in comune.

1

Puoi fare ricorsive include in questo modo, ma in generale dovrai anche usare qualche tipo di trucco di protezione dell'intestazione - altrimenti il ​​preprocessore andrà in una ricorsione infinita. Questo non sarà davvero aiutare a risolvere il problema di fondo, perché si ha essenzialmente due classi, ognuna delle quali reciprocamente richiedono di vedere la dichiarazione completa degli altri al fine di compilare:

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 

Non importa che uno si mette in primo luogo, non sarà in grado di compilare perché ha bisogno di conoscere tutti i dettagli dell'altro.

+0

E poiché i dettagli completi dell'altra classe sono necessari per ogni classe, una [dichiarazione in avanti] (http://stackoverflow.com/q/553682/1497596) non aiuta. Tuttavia, se il file include per esempio, la classe 'A', contiene solo puntatori o riferimenti alla classe' B', quindi una dichiarazione diretta alla classe 'B' nella classe' A' può rendere possibile la compilazione. – DavidRR

1

Questo tipo di inclusione circolare non è consentita dalla C++, ma questo dovrebbe funzionare:

Invece di includere IFr.h, utilizzare una dichiarazione anticipata.

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

Questo renderà mainw compilazione bene, ma tutto il codice che utilizza il membro ifr deve includere IFr.h troppo.

Questo funziona solo perché ifr è un membro static. In caso contrario, il compilatore dovrebbe conoscere la dimensione esatta di ifr.

Inoltre, come hanno detto molte altre persone, dovresti includere guardie attorno a entrambe le intestazioni per evitare errori che provengono dall'includere due volte la stessa intestazione.

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

Si può fare:

// 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 nel caso CSize ha bisogno di cambiare in fase di esecuzione utilizzare una soluzione di puntatore come @ChrisW risposta spettacoli.

Problemi correlati