2011-02-08 16 views
13

Per favore, istruiscimi. Perché questo compilazione:Dipendenza circolare C++ - namespace vs struct

struct compiles 
{ 
    struct A; 
    struct B 
    { 
     B(const A &a) : member(a.member) { } 
     int member; 
    }; 
    struct A 
    { 
     A(const B &b) : member(b.member) { } 
     int member; 
    }; 
}; 

mentre questo non:

namespace doesnt 
{ 
    struct A; 
    struct B 
    { 
     B(const A &a) : member(a.member) { } 
     int member; 
    }; 
    struct A 
    { 
     A(const B &b) : member(b.member) { } 
     int member; 
    }; 
} 

(in MSVC 9.0)

+1

Qual è l'errore del compilatore che stai ottenendo? –

+0

+1 per 'namespace doesnt' – TonyK

risposta

7

In C++, l'ambito di classe è speciale. Qualsiasi dichiarazione che si estenda o superi la definizione della classe viene automaticamente estesa alle regioni definite dalle definizioni dei membri (3.3.6 [basic.scope.class]).

Ciò significa che nel primo caso, sia la prima dichiarazione del struct A e la definizione completa di struct A sono visibili nel corpo del B e suo costruttore.

Ciò non vale per namespace portata così nel secondo caso a.member nel costruttore di B è un errore perché una definizione di struct A non è ancora visibile.

+0

+1 per il riferimento standard, grazie! – Bill

14

Il corpo di una definizione class/struct/union viene elaborato tutto in una volta, permettendo riferimenti a membri di classi definiti in seguito. Un namespace viene elaborato dall'alto verso il basso e una dichiarazione in avanti di struct A non consente di utilizzare i suoi membri senza una definizione. Prova a spostare la definizione del costruttore di B fuori dalla classe in modo da poterla inserire dopo la definizione di A.

+0

+1 per una soluzione al problema :) –

3

[Testato anche con g ++ 4.2] Il primo viene compilato perché il compilatore riprende tutti i tipi definiti all'interno della struttura prima di compilare effettivamente le strutture nidificate (pensa ai metodi inline pubblici che utilizzano gli attributi privati ​​che appaiono più avanti nella classe) . All'interno del namespace il compilatore funziona semplicemente dall'alto verso il basso e non ha regole speciali.

0

entrambi verranno compilati se si spostano le implementazioni dei costruttori nel file .cpp in cui dovrebbero essere comunque.