2009-08-15 14 views
13

w projekcie mam 2 klas:Circular C++ nagłówka

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

Ale nie mogę skompilować ten kod, błąd w linii static IFr ifr;. Czy ten rodzaj wzajemnej integracji jest zabroniony?

+1

Zakładam, że powinno to być najważniejsze: CSize –

Odpowiedz

15

Czy ten rodzaj krzyża -włączenia są zabronione?

Tak.

obejście byłoby powiedzieć, że członek IFR z mainw jest odniesienie lub wskaźnik, tak że przód-deklaracja zrobi zamiast tym pełną deklarację, jak:

//#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; 
... 
} 

Alternatywnie , zdefiniuj wartość CSize w oddzielnym pliku nagłówkowym (aby Ifr.h mógł dołączyć ten inny plik nagłówkowy zamiast do mainw.h).

0

Jeśli masz

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

owinięta kodzie, wtedy powinno być dobrze :)

[EDIT] Kod pisownia: O: P

+0

To nie pomogłoby w tym przypadku. – ChrisW

+0

To naprawdę nie pomogłoby w tym przypadku - powinno być oczywiste, że główna klasa wyraźnie będzie musiała zobaczyć pełną deklarację klasy Ifr, zanim będzie mogła skompilować –

+0

Oboje macie rację. Chyba byłem trochę za szybki na spuście :) – cwap

4

Nie możesz mieć dwóch klas, które osadzają się w ten sposób. Można zrobić jeden z nich wskaźnik:

class foo; 

class bar 
{ 
    foo* fooPtr; 
} 

trzeba by skonstruować foo i przypisać ją do fooPtr konstruktora w barze i bezpłatny go w destructor - to z pewnością nieco więcej pracy.

Albo, w tym przypadku, jak sugerował jeden z komentatorów, make mainw :: size a define i umieść go gdzieś pospolitym.

1

Możesz wykonywać rekursywne fragmenty podobne do tego, ale generalnie musisz również użyć jakiejś sztuczki straży nagłówka - w przeciwnym razie preprocesor przejdzie do nieskończonej rekurencji. Nie będzie to naprawdę pomóc rozwiązać podstawowy problem, ponieważ mają zasadniczo dwóch klas, z których każda wzajemnie wymagają, aby zobaczyć pełną deklarację drugi w celu zestawienia:

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 

Bez względu na to, który z nich można umieścić po pierwsze, nie będzie w stanie się skompilować, ponieważ musi znać pełne szczegóły drugiego.

+0

A ponieważ wszystkie klasy są wymagane przez każdą klasę, nie pomaga [forward declaration] (http://stackoverflow.com/q/553682/1497596). Jeśli jednak plik włączający, np. Klasa "A", zawiera tylko wskaźniki lub odwołania do klasy "B", wówczas deklaracja przekazania do klasy "B" w klasie "A" może umożliwić kompilację. – DavidRR

1

Ten rodzaj integracji kołowego nie jest dozwolone przez C++, ale to powinno działać:

Zamiast tym IFr.h użyć do przodu deklarację.

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

To sprawi mainw kompilacji dobrze, ale cały kod, który wykorzystuje element ifr musi zawierać IFr.h też.

Działa to tylko dlatego, że ifr jest członkiem static. W przeciwnym razie kompilator musiałby znać dokładny rozmiar ifr.

Ponadto, jak powiedziało wiele osób, powinieneś dołączyć strażników do obu nagłówków, aby uniknąć błędów, które pochodzą z dwukrotnego włączenia tego samego nagłówka.

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

można zrobić:

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

lub w przypadku cSize musi się zmienić w czasie wykonywania użyć roztworu wskaźnika jako @ChrisW pokazy odpowiedzi.