2011-12-01 175 views
7

我試圖低於該虛設碼來測試未命名的名稱空間。命名空間具有相同的變量具名命名空間聲明

我有以下的輸出

ctor 1 
ctor 0 
3 
5 

我對此感到有點困惑。

  1. 我是在編譯器說,它不能解析 歧義關於a::m_a期待一個錯誤。相反,它始終指向嵌套較少的 。情況總是如此嗎? C++遵循什麼規則?
  2. 看來,編譯器下面寫在文件中的順序 創建變量CMyObj。情況總是如此嗎?
  3. 有沒有什麼辦法來訪問最嵌套m_a變量 從main()
class CMyObj{  
    public: 
    CMyObj(int a){std::cout << "ctor " << a << std::endl; } 
}; 
namespace a{ 
     namespace{ 
      int m_a=4; 
      int m_b=5; 
      CMyObj m_obj(1); 
     } 
} 
namespace a{ 
     int m_a=3; 
     CMyObj m_obj(0); 
} 
int main(){ 
     std::cout << a::m_a << std::endl; // which one? 
     std::cout << a::m_b << std::endl; // how this is possible? 
     return 0; 
} 

回答

3

我沒有C++ 03的標準跟我來檢查措辭那裏,所以我會從FDIS n3290報價。我認爲這個問題的答案在限定的名稱查找規則被發現在3.4.3.2/2:

For a namespace X and name m, the namespace-qualified lookup set S(X,m) is defined as follows: Let S0(X,m) be the set of all declarations of m in X and the inline namespace set of X (7.3.1). If S0(X,m) is not empty, S(X,m) is S0(X,m); otherwise, S(X,m) is the union of S(Ni,m) for all namespaces Ni nominated by using-directives in X and its inline namespace set.

現在,請記住具名命名空間是唯一命名的命名空間與使用指令。

+0

最後一句是關鍵。謝謝。 –

+0

嗨基因!非常感謝您的回放(延遲一段時間)! –

1

我應該花時間找到規範的確切定義,但是當你有一個匿名(未命名)命名空間,編譯器實際上產生一個錯位的名稱。當你寫

a::m_b 
第二 std::cout聲明

,編譯器會自動替換錯位的名稱,以便您可以訪問它。從基因Bushuyev後來的回答內容包括:

Now, remember that unnamed namespace is a uniquely named namespace with a using directive.

在碰撞名稱的情況下,編譯器知道什麼a::m_a手段,所以它使用。它是名稱空間頂層的一個。我不認爲有什麼辦法可以到達m_a的未命名名稱空間副本。

本頁面做了解釋命名空間的一份體面的工作。 Winterdom: On C++ Namespaces

+0

「我不認爲有什麼辦法可以到達m_a的未命名名稱空間副本。」 - 似乎你可以再次打開未命名的名稱空間來添加一個存取函數/別名。 – visitor

1

在這個簡化的代碼首先看(和我簡單的解釋,你可以閱讀§3.4.3.2的細節):

namespace a 
{ 
    int x; 
} 

int main() 
{ 
    int i = a::x; 
} 

考慮,當我們說a::x會發生什麼。首先,編譯器枚舉a中的所有x的聲明。如果它發現一個明確的x,它會成功完成。否則,它會遞歸地搜索由using-directive聲明的名稱空間。如果它從未發現結果,則該程序不合格。

namespace a 
{ 
    int x; 
} 

namespace b 
{ 
    using namespace a; 
} 

int main() 
{ 
    int i = b::x; 
} 

在這裏,它沒有找到在bx,所以它搜索名字空間a(因爲使用指示符),並發現它。現在應該是有意義爲什麼這一點也不含糊:

namespace a 
{ 
    int x; 
} 

namespace b 
{ 
    using namespace a; 
    int x; 
} 

int main() 
{ 
    int i = b::x; 
} 

這裏找到在bx從不認爲a。現在只是考慮到不具名命名空間實際上只是一個具有獨特的未知名的命名空間:

namespace b 
{ 
    namespace 
    { 
     int x; 
    } 

    // this is what an unnamed namespace expands to (in exposition) 
    namespace __unique__ {} 
    using namespace __unique__; 

    namespace __unique__ 
    { 
     int x; 
    } 

    int x; 
} 

int main() 
{ 
    int i = b::x; 
} 

像以前一樣,在bx不考慮具名命名空間中找到。你的代碼很相似。

+0

我喜歡你的詳細解釋。 –

0

因爲namespace::<unnamed>::m_a的範圍是外部命名空間(namespace::a),所以沒有歧義。在主函數中沒有辦法訪問namespace::<unnamed>::m_a,這就是爲什麼沒有歧義。嘗試編譯下面的代碼,你會得到錯誤:

namespace ns{ 
    namespace { 
    int a = 2; 
    } 
    int a = 3; 
    int c = a; 
} 

居住在同一個翻譯單元的全局變量將在他們聲明的順序進行初始化。在不同翻譯單元中聲明的全局變量的初始化順序是未定義的。