2012-09-20 118 views
3

從C++ 11標準的第7.3.4.2的:範圍的C++ using指令

使用指示符指定在指定名稱空間 的名稱可以在範圍內使用其中使用指令出現在 ,使用指令之後。在非限定名稱查找(3.4.1)期間,名稱 看起來好像它們在最近的封閉名稱空間 中聲明的一樣,其中包含使用指令和提名的命名空間。 [ 注:在此上下文中,「包含」意味着「直接包含或間接包含」。 - 注意]

第二句和第三句是什麼意思?請舉例。

這裏是我試圖理解代碼:

namespace A 
{ 
    int i = 7; 
} 
namespace B 
{ 
    using namespace A; 
    int i = i + 11; 
} 
int main(int argc, char * argv[]) 
{ 
    std::cout << A::i << " " << B::i << std::endl; 
    return 0; 
} 

它打印 「7 7」,而不是 「7月18日」 爲我所期望的。

對不起,錯誤的程序實際打印「7 11」。

+2

此處的行爲未定義。 'namespace B'中的兩個'i'實例指向同一個變量(只要它的* declarator *被看到,即在初始化之前,它就會影響'A :: i')。所以它被初始化時自己的垃圾值增加了11. –

+0

好的,爲什麼它會在'使用命名空間A'之後影響'A :: i'。這是標準中的段落在談論什麼? – ThomasMcLeod

+1

@ThomasMcLeod:這就是陰影*意味着*:隱藏了一個定義。由於您沒有限定在表達式中使用'i',因此無法查找。由於C++允許你引用你剛纔定義的變量,所以即使在初始化表達式中,'i'將是新的,而不是'A'中的。 –

回答

2

消除了不確定的行爲:

namespace A 
{ 
    int i = 7; 
} 
namespace B 
{ 
    using namespace A; 
    int tmp = i + 11; 
    int i = tmp; 
} 
#include <iostream> 
int main() 
{ 
    std::cout << A::i << " " << B::i << std::endl; 
    return 0; 
} 

標準的含義是,在該行

int tmp = i + 11; 

i出現在其中既包含using-的「最近的封閉命名空間中的名稱指令和指定命名空間「; 使用指令出現在namespace B中,而提名的命名空間是namespace A;最近的封閉名稱空間是全局名稱空間,所以i顯示爲::i。這意味着如果名稱i已經存在於全局名稱空間中,則代碼不明確。

對於更復雜的例子:

namespace A { 
    namespace B { 
     namespace C { 
      int i = 4; 
     } 
    } 
    namespace D { 
     using namespace B::C; 
     namespace E { 
      int j = i; 
     } 
    } 
} 

在線路int j = ii出現在使用指示符(即,A::D)和提名命名空間(A::B::C)的最近的封閉空間,它是A 。所以,內A::D後使用指示符,所以也內A::D::E,不合格的名稱i可以指A::B::C::i顯示爲A::i,遮蔽任何::i,與任何A::i衝突的,並通過任何A::D::iA::D::E::i(內A::D::E)被遮擋的:僅僅因爲名字不合格的名稱查找過程中會顯示爲A::i

int i = 1;    // shadowed by A::B::C::i appearing as A::i 
namespace A { 
    int i = 2;   // conflicts with A::B::C::i appearing as A::i 
    namespace B { 
     int i = 3;  // irrelevant 
     namespace C { 
      int i = 4; // nominated; appears as A::i 
     } 
    } 
    namespace D { 
     int i = 5;  // shadows A::B::C::i appearing as A::i 
     using namespace B::C; 
     namespace E { 
      int i = 6; // shadows A::B::C::i appearing as A::i 
      int j = i; 
     } 
    } 
} 

注意,這並不意味着,它實際上是;限定名稱A::i將繼續僅指實際名稱A::i(如果存在)。

+0

我還不確定這應該如何工作。所以當標準說「出現」時,這只是爲了名稱隱藏又名陰影的目的嗎?如果是這種情況,那麼上面的代碼應該在'int j = i'處產生名稱衝突。 – ThomasMcLeod

+0

@ThomasMcLeod你指的是哪個代碼?哪個'我'碰撞? – ecatmur

+0

我的意思是說,如果我們註釋到語句「int i = 5;'和'int i = 6;',那麼在語句int j = i處應該有一個涉及'i'的名稱衝突;'。但在上面的代碼中,「A :: D :: i」和「A :: D :: E :: i」的存在掩蓋了碰撞。 – ThomasMcLeod

4

代碼中的using聲明是無關緊要的。當B::i的初始化程序被評估時,B::i已經在範圍內。你可以通過刪除using聲明來證明這一點;你的代碼應該編譯並運行。在任何情況下,B::i的值最終都是未定義的,因爲它取決於未初始化的值(即在初始化器評估時B::i具有的值)。