2010-01-27 17 views
8

Dire che ho un foo classe con un oggetto di bar classe come un membroQual è il modo migliore per gestire le classi co-dipendenti in C++?

class foo 
{ 
    bar m_bar; 
}; 

bar Supponiamo ora che ha bisogno di tenere traccia del foo che lo possiede

class bar 
{ 
    foo * m_pfoo; 
} 

Le due classi di riferimento tra loro e senza una dichiarazione anticipata, non verrà compilato. Così l'aggiunta di questa riga prima della dichiarazione di foo risolve questo problema

class bar; 

Ora, qui è il problema - quando si scrivono i file header, ogni intestazione dipende dall'altro: foo.h ha bisogno di definizioni di cui bar.h e vice versa. Qual è il modo corretto di affrontare questo?

risposta

23

È necessario spostare tutti i membri dell'accesso dall'intestazione e nei file di origine.

In questo modo, è possibile inoltrare dichiarare le classi nell'intestazione, e definirli in foo:

// foo.h 
class bar; 

class foo { 
    bar * m_pbar; 
} 

// bar.h 
class foo; 
class bar { 
    foo * parent; 
} 

che vi permetterà di lavorare - non si può mettere le definizioni che richiedono informazioni sui membri nella vostra header - spostalo nel file .cpp. I file .cpp possono includere sia foo.h sia bar.h:

// Foo.cpp 
#include "foo.h" 
#Include "bar.h" 

void foo::some_method() { 
    this->m_pbar->do_something(); // Legal, now, since both headers have been included 
} 
+0

Questa sembra l'opzione migliore per ciò di cui ho bisogno. –

+1

ora come funziona questa soluzione se le tue classi codipendenti sono basate su modelli e quindi non possono essere separate in file header e cpp? –

0

Per quanto ne so, l'unico vero modo per farlo è utilizzare i puntatori poiché non richiedono la definizione della classe fino all'unità di traduzione (.cpp) nel qual caso entrambe le classi saranno state definite correttamente.

2

Suppongo che un modo sia rendere le classi di interfaccia astratte senza membri. Quindi sottoclasse foo e bar da quelle classi di interfaccia.

esempio:

class FooInterface 
{ 
    // methods here 
} 

class BarInterface 
{ 
    // methods here 
} 

class Foo : public FooInterface 
{ 
    BarInterface *pBar; 
} 

class Bar : public BarInterface 
{ 
    FooInterface *pFoo; 
} 

Questo rompe il ciclo delle dipendenze (a meno che le interfacce stesse dipendono l'uno dall'altro, e se questo è il caso, allora si dovrebbe probabilmente essere dichiarata nello stesso file)

1

In il tuo esempio, foo dipende da bar (perché contiene un oggetto effettivo bar), ma bar non dipende da foo (poiché contiene solo un foo *). Ora bar dipende da foo come nome del tipo, quindi bar.h ha bisogno di una dichiarazione anticipata del nome: class foo;. foo dipende da bar, quindi foo.h deve contenere #include "bar.h"

Non è possibile avere classi che dipendano direttamente l'una dall'altra in C++; semplicemente non funziona. È necessario disaccoppiare le classi in modo tale che una dipende solo dall'altra esistente, come nell'esempio. Le uniche cose che creano una dipendenza diretta stanno usando una classe come classe base o come campo; qualsiasi altro uso crea solo una dipendenza indiretta, che in genere non è un problema.

Problemi correlati