2011-06-15 119 views
15

是否有未命名空间的这两个嵌套用法之间的功能区别:嵌套未命名空间

namespace A { namespace { 
    void foo() {/*...*/} 
}} 

namespace { namespace A { 
    void foo() {/*...*/} 
}}} 

据我看到它,都foo旨意得到一个内部唯一每个编译单元的标识符,可以通过A::foo进行访问 - 但是有没有我看不到的微妙或不那么细微的差异?

+1

(编辑)您可以通过在文件级声明另一个'A :: foo'来有效地隐藏第二个'foo'。第一个'foo'将总是以':: A :: foo'的形式访问。除非你重新打开'A'并在那里声明另一个'foo'。也就是说,几乎相同。 – 2011-06-15 13:55:17

回答

7

与您输入的内容完全相同,没有区别。

当然,您可以在展台示例的第一级名称空间中添加声明,然后它将会有所不同。

namespace A { 
    int i;   // Accessed globally in this file as "A::i". 
    namespace { 
    void foo() {/*...*/} 
}} 


namespace { 
    int i;   // Accessed globally in this file simply as "i". 
    namespace A { 
    void foo() {/*...*/} 
}}} 

需要注意的是,虽然你程序员没有办法区分,编译器,命名空间是不同的:

unnamed_namespaces.cpp:42:5: error: reference to ‘A’ is ambiguous 
unnamed_namespaces.cpp:19:17: error: candidates are: namespace A { } 
unnamed_namespaces.cpp:28:19: error:     namespace <unnamed>::A { } 

有用:


编辑:

在对于ADL(参数相关的名称查找),我明白,这将是在重载其他foo()没有优先级差异如下:

#include <iostream> 

void foo() { std::cout << "::foo()" << std::endl; } 

namespace A { 
    namespace { 
     void foo() { std::cout << "A::<unnamed>::foo()" << std::endl; } 

     class AClass 
     { 
     public: 
      AClass() 
      { foo(); } 
     }; 
    } 
} 


namespace { 
    namespace B { 
     void foo() { std::cout << "B::<unnamed>::foo()" << std::endl; } 

     using namespace A; 

     class BClass 
     { 
     public: 
      BClass() 
      { foo(); } 

      ~BClass() 
      { A::foo(); } 
     }; 
    } 
} 

int main() 
{ 
    A::foo(); 
    B::foo(); 
    foo(); 

    A::AClass a; 
    B::BClass b; 

    return 0; 
} 

C除非明确指定,否则ompiler将更喜欢最接近的foo()。 所以BClass构造函数调用B::foo()甚至有一个using namespace A就可以了。 若要在BClass析构函数上调用A::foo(),则必须明确限定该调用。

A::<unnamed>::foo() 
B::<unnamed>::foo() 
::foo() 
A::<unnamed>::foo() 
B::<unnamed>::foo() 
A::<unnamed>::foo() 

也许如果我们认为嵌套命名为命名空间以及如何参数相关会解决它变得更加清晰。 olny的区别将是隐式的using在未命名的,但它不会改变编译器偏好。

+2

我认为你的访问示例是倒退。第一个是'A :: i',第二个就是'i'。 – 2011-06-15 21:06:41

+0

谢谢丹尼斯。我纠正了这一点。 – j4x 2011-06-16 17:57:43

+0

尽管迄今为止这是一个很好的答案,但我想知道命名空间对ADL有什么影响 - 命名空间A {void bar();}能够在任何例子? – ltjax 2011-06-17 09:46:33