2012-05-24 79 views
12

考慮下面的代碼:是否使用名稱空間導致名稱隱藏?

namespace C { 
    class X {}; 
} 

namespace A { 
    class X {}; 

    namespace B { 
     using namespace C; 

     X x; 
    } 
} 

我期待的x類型爲C::X由於using namespace指令,而是既VS2010和命名空間B內在線LLVM/Clang的編譯決心XA::X。使用使用聲明(using C::X)更改using指令,然後按預期方式解決爲C::X

的標準說使用指令在[7.3.4.2]:

A,使用-指令指定,在指定名稱空間中的名稱可以在其中使用指示符的使用後出現的範圍內使用-指示。在非限定名稱查找(3.4.1)期間,這些名稱看起來好像是在最近的包含using-directive和提名名稱空間的封閉名稱空間中聲明的。

我對此的解讀是,彷彿命名空間B內聲明,從而有效地隱藏A::XC::X應該會出現。標準中的哪些部分背後是使用指令和使用聲明之間的不一致?有沒有辦法通過using指令來隱藏外部作用域的名稱?

+5

也許線索在*中,這些名字看起來好像它們是在最近的封閉名稱空間中聲明的一樣,它們都包含** using-directive和提名的名稱空間*。那不是'::'?如果是這樣的話,會不會先找到A :: X(查找從內部命名空間出來)......但是不確定,但是g ++也提取了'A :: X',所以它非常*在編譯器中保持一致。 –

+0

@DavidRodríguez - dribeas:哦,那會解釋它... –

回答

6

使用指令本章似乎莫名其妙清楚,你所看到的預期行爲:

7.3.4p2一個using指令規定,在指定的命名空間的名稱可以使用在use-directive之後出現using-directive的範圍內。在非限定名稱查找(3.4.1)期間,這些名稱看起來好像它們是在最近的封閉名稱空間中聲明的,其中包含兩個 using-directive和指定的名稱空間。

7.3.4p3 using-directive不會將任何成員添加到它出現的聲明區域。

即,使用指示符添加命名空間的成員的查找組指令的共同命名空間的祖先和所使用的命名空間的,而不是直接向範圍,其中使用指示符用來。第二條報價明確指出:它不會將任何成員添加到使用指令的聲明區域。

後來有是爲了說明別的一個例子,但實際顯示這一點:

7.3.4p4 [...]對於另一個例子

namespace A { 
    int i; 
} 
namespace B { 
    int i; 
    int j; 
    namespace C { 
    namespace D { 
     using namespace A; 
     int j; 
     int k; 
     int a = i; // B::i hides A::i 
    } 

這最後一個例子用於闡明傳遞性(並且包含更多的代碼),但是一旦刪除了額外的代碼,它實際上就等同於您的代碼。

因此,看起來在您的情況下,使用指令不是隱藏,而是隱藏。

+0

因此,對於我的第二個問題,我假設它**是**可能通過使用指令隱藏名稱,但只有當它們位於常見的命名空間祖先。 –

+0

我會這麼說。無論如何,我會完全避免* using-directives *,並且很少使用* using-declarations *。查找變得複雜得多,很難確定究竟在使用什麼,在哪裏定義......如果你的需要是扁平化使用複雜的嵌套命名空間,請考慮* namespace aliases *。 –

+0

我在我的真實代碼中避免了_using-directives_,這只是嘗試通過利用名稱查找規則來'找到類存在的位置'。 –