2015-05-05 12 views
7

Quindi sto creando un progetto che comporta l'annidamento di vettori l'uno dentro l'altro, ma la struttura non verrà compilata. Penso che questo sia un caso di dipendenza circolare, ma tutte le correzioni che ho visto sembrano riguardare solo il codice che coinvolge file di intestazione e unità di traduzione separate.Come risolvere una dipendenza circolare della classe con una classe base condivisa senza intestazioni?

#include <iostream> 
#include <vector> 

class A { 
public: 
    virtual ~A(); 
}; 

// The following forward declaration statements didn't solve the 
// compiler error: 
// class C; 
// class C : public A; 

class B : public A { 
    std::vector<A*> Avector;  
public: 
    void addC(C* Cin){Avector.push_back(Cin);} 
    ~B(); 
}; 

class C : public A { 
    std::vector<A*> Avector;   
public: 
    void addB(B* Bin){Avector.push_back(Bin);} 
    ~C(); 
}; 

int main() { 
    B b; 
    C c; 
    b.addC(&c); 
    c.addB(&b); 
} 

Ho provato in avanti dichiarando con

class C; 
Class C : public A; 

Ma niente di tutto ciò sembra funzionare.

L'errore che ottengo è:

\test\test\source.cpp(15): error C2061: syntax error : identifier 'C' 
\test\test\source.cpp(15): error C2065: 'Cin' : undeclared identifier 

È questo il tipo di codice attuabile?

risposta

7

"... ma tutte le correzioni che ho visto sembrano riguardare solo il codice che coinvolge file di intestazione e unità di traduzione separate."

ho ben d'accordo che un Q popolare & A come Resolve circular dependencies in c++ in realtà non rispondere alla tua domanda come gestire questo all'interno di un unico file di implementazione (intestazione o no).

Tuttavia, IMHO è considerato la pratica migliore (e come si potrebbe raccogliere da these pointers), per separare le dichiarazioni di classe nelle intestazioni e implementazione/definizione nelle proprie unità di traduzione.
Anche con le sole intestazioni (ad esempio class template), è consigliabile prendere in considerazione una dichiarazione di classe separata (senza codice inline) e fornire l'implementazione in un file sorgente separato, incluso in tale file.

Il tuo problema è in realtà qui:

class B : public A { 
    // ... 
    void addC(C* Cin) { Avector.push_back(Cin); } 
        // ^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
    // ... 
}; 

A questo punto (anche con una dichiarazione anticipata di class C;) il compilatore non sa come convertire C*-A*, perché le informazioni sulla relazione di ereditarietà è mancante (e no, non è possibile rendere dichiarazioni anticipate come class C : public A;).

"È possibile implementare questo tipo di codice?"

È possibile fare tutto questo in un file di singola unità di traduzione/intestazione:

Invece di inlining la definizione di funzione con la dichiarazione di classe B s', si dovrebbe separare fuori per essere visto dopo il piena dichiarazione di class C:

class C; 

class B : public A { 
    // ... 
    void addC(C* Cin); 
}; 

class C : public A { 
    // ... 
}; 

inline void B::addC(C* Cin) { Avector.push_back(Cin); } 

class C vedrà la piena dichiarazione di class B comunque (a causa di ordine di dichiarazione). Così è OK per utilizzare l'implementazione

void addB(B* Bin) { Avector.push_back(Bin); } 

dall'interno dichiarazione class C.

+1

Non è necessario inserire la definizione in un'altra unità di compilazione. la definizione di 'B :: AddC' dovrebbe essere dopo la definizione di' C'. – Jarod42

+0

@ Jarod42 Deve essere contrassegnato come "in linea", quindi? –

+0

Sembra che tutto il codice dell'OP si trovi in ​​una singola unità di traduzione, quindi no, non è richiesto. Se il codice era nel file di intestazione, sì. – Jarod42

1

Avevo provato in avanti dichiarando, e avevo provato a mettere l'implementazione della funzione dopo la seconda parte, ma non avevo provato entrambi contemporaneamente. Il codice fisso per chiunque googling questo 10 anni dopo:

#include<iostream> 
    #include<vector> 

    using namespace std; 

    class C; 

    class A 
    { 
    public: 
     virtual ~A(); 
    }; 

    class B : public A 
    { 
    public: 
     vector<A*> Avector; 

     void addC(C* Cin); 
     ~B(); 
    }; 

    class C : public A 
    { 
    public: 
     vector<A*> Avector; 

     void addB(B* Bin) 
     { 
      Avector.push_back(Bin); 

     }; 
      ~C(); 
     }; 

    void B::addC(C* Cin) 
    { 
     Avector.push_back(Cin); 
    } 

    int main() 
    { 

    } 

I miei ringraziamenti a πάντα ῥεῖ, e un grido di Jarod42.

+1

Non è necessario inviare di nuovo una risposta. Che tu abbia contrassegnato il mio accettato, dichiara già di aver risolto il problema a nome di esso (ho anche aggiunto alcuni piccoli miglioramenti). –

Problemi correlati