2011-02-08 62 views
13

請教育我。爲什麼這編譯:C++循環依賴 - 命名空間vs結構

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

雖然這並不:

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

(在MSVC 9.0)

+1

你得到的編譯器錯誤是什麼? – 2011-02-08 21:59:14

+0

+1命名空間不適用 – TonyK 2011-02-08 22:37:45

回答

7

在C++中,類範圍是特殊的。任何擴展到或超過類定義結束的聲明都會自動擴展到由其成員定義(3.3.6 [basic.scope.class])定義的區域。

這意味着在第一種情況下,struct A的第一個聲明和struct A的完整定義在B及其構造函數的主體中都可見。

這不適用於命名空間範圍,所以在第二種情況下a.memberB的構造函數中是一個錯誤,因爲struct A的定義尚不可見。

14

一個class/struct/union定義的主體都處理一次,使對稍後定義的類成員的引用。 A namespace從上到下進行處理,並且前向聲明struct A不允許您在沒有定義的情況下使用其成員。嘗試將B的構造函數的定義移出課堂,以便您可以將它放在A的定義之後。

+0

+1對於問題的解決方案:) – 2011-02-09 07:24:44

3

[也用g ++ 4.2測試過]第一個編譯是因爲編譯器在實際編譯嵌套結構之前完全獲取了結構體中定義的所有類型(使用後面出現的私有屬性考慮公共內聯方法) 。在命名空間中,編譯器只是從上到下工作,並沒有特殊的規則。

0

如果您將構造函數的實現移動到.cpp文件中,它們都應該編譯它們應該在哪裏。