Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/153.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 具有未命名命名空间且声明了相同变量的命名空间_C++_Namespaces - Fatal编程技术网

C++ 具有未命名命名空间且声明了相同变量的命名空间

C++ 具有未命名命名空间且声明了相同变量的命名空间,c++,namespaces,C++,Namespaces,我尝试了下面的伪代码来测试未命名的名称空间 我有以下输出 ctor 1 ctor 0 3 5 我对此有点困惑 我以为编译器会出错,说它无法解析 关于a::m_a的歧义。相反,它总是指 少嵌套。总是这样吗?C++遵循的规则是什么?< /LI> 编译器似乎按照以下顺序创建变量CMyObj 写在文件上。总是这样吗 有没有办法访问嵌套最多的m_a变量 从main() 类CMyObj{ 公众: CMyObj(int a){std::cout我应该花些时间在规范中找到确切的定义,但是当您有一个匿名

我尝试了下面的伪代码来测试未命名的名称空间

我有以下输出

 ctor 1
 ctor 0
 3
 5
我对此有点困惑

  • 我以为编译器会出错,说它无法解析 关于a::m_a的歧义。相反,它总是指 少嵌套。总是这样吗?C++遵循的规则是什么?< /LI>
  • 编译器似乎按照以下顺序创建变量CMyObj 写在文件上。总是这样吗
  • 有没有办法访问嵌套最多的
    m_a
    变量 从
    main()
    类CMyObj{
    公众:
    
    CMyObj(int a){std::cout我应该花些时间在规范中找到确切的定义,但是当您有一个匿名(未命名)名称空间时,编译器实际上会生成一个损坏的名称

    a::m_b 
    
    在第二个
    std::cout
    语句中,编译器将自动替换损坏的名称,以便您可以访问它。根据Gene Bushuyev随后的回答:

    现在,请记住,未命名名称空间是一个唯一命名的名称空间 使用using指令


    在名称冲突的情况下,编译器知道
    a::m_a
    的意思,所以它使用了它。它位于名称空间的顶层。我认为目前没有任何方法可以获得m_a的未命名名称空间副本


    本页在解释名称空间方面做得很好。

    我没有C++03标准来检查其中的措辞,因此我将引用FDIS n3290。我认为这个问题的答案可以在3.4.3.2/2中的限定名称查找规则中找到:

    对于名称空间X和名称m,名称空间限定查找集S(X,m)的定义如下:设S0(X,m)是X中m的所有声明的集合,内联名称空间集是X(7.3.1)。如果S0(X,m)不是空的,则S(X,m)是S0(X,m);否则,S(X,m)是S(Ni,m)的并集对于使用X中的指令及其内联命名空间集指定的所有命名空间


    现在,请记住,未命名名称空间是具有using指令的唯一命名名称空间。

    首先查看此简化代码(以及我的简化解释,您可以阅读§3.4.3.2了解详细信息):

    考虑一下当我们说
    a::x
    时会发生什么。首先,编译器枚举
    a
    x
    的所有声明。如果它找到一个明确的
    x
    ,它将成功完成。否则,它将递归搜索using指令声明的名称空间。如果它从未找到结果,则程序的格式不正确

    namespace a
    {
        int x;
    }
    
    namespace b
    {
        using namespace a;
    }
    
    int main()
    {
        int i = b::x;
    }
    
    在这里,它在
    b
    中找不到
    x
    ,因此它搜索名称空间
    a
    (因为使用指令)并找到它。现在应该可以理解为什么这并不含糊:

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

    这里在<代码> b <代码>中找到<代码> x <代码>,并且从未考虑<代码> 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;
    }
    

    与前面一样,
    b
    中的
    x
    没有考虑未命名的命名空间。您的代码类似。

    没有歧义,因为
    命名空间的范围:::m_a
    是外部命名空间(
    命名空间::a
    )。无法访问主函数中的
    命名空间:::m_a
    ,因此没有歧义。请尝试编译以下代码,您将得到错误:

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

    驻留在同一翻译单元中的全局变量将按照声明的顺序进行初始化。在不同翻译单元中声明的全局变量的初始化顺序未定义。

    最后一句是关键。谢谢。嗨,Gene!非常感谢您的重播(延迟发布)!我喜欢您的详细解释。“我认为目前没有任何方法可以获得m_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;
    }
    
    namespace ns{
      namespace {
        int a = 2;
      }
      int a = 3;
      int c = a;
    }