使用指令 - 为什么这么奇怪的行为?

时间:2014-12-11 22:23:28

标签: c++

我有这个示例代码

namespace ns1
{
    void foo(int)
    {
    }
}

namespace ns2
{
    void foo()
    {
    }
    void bar()
    {
        using namespace ::ns1;
        foo(42); // why compiler can't just call ns1::foo?
    }
}

它不会编译错误:

prog.cpp:16:9: error: too many arguments to function ‘void ns2::foo()’

我在C ++ 2003标准中找到了这个错误的原因:

  

using-directive指定指定名称空间中的名称   可以在using指令出现的范围内使用   使用指令。在非限定名称查找(3.4.1)期间,名称   看起来好像是在最近的封闭命名空间中声明的   它包含using-directive和指定的命名空间。   [注意:在此上下文中,“包含”表示“直接包含或   间接地”。 ]

这条奇怪的规则有理由吗?为什么命名空间ns1中的名称不能直接出现在名称空间ns2中?

2 个答案:

答案 0 :(得分:9)

我相信这是为了减少冲突和惊喜。由using指令引入范围的名称是可见的,但是直接包含在本地范围中的任何内容都将优先于它。

如果你真的想在没有合格身份证的情况下给你打电话,那么你可以用using声明来宣传它:

namespace ns1 {
    void foo(int) { }
}

namespace ns2 {
    void foo() { }
    void bar() {
        using ::ns1::foo;
        foo(42); // No problem; calls ::ns1::foo.
    }
}

答案 1 :(得分:2)

ns1::foons2::foo

的声明隐藏起来

来自N3337,§3.3.10/ 1 [basic.scope.hiding]

  

可以通过嵌套声明性区域或派生类(10.2)中相同名称的显式声明来隐藏名称。

您引用的部分(§7.3.4/ 2 )后面会紧跟

  

3 using-directive 不会将任何成员添加到它出现的声明区域。 [例如:

    namespace A {
      int i;
      namespace B {
        namespace C {
          int i;
        }
        using namespace A::B::C;
        void f1() {
          i = 5; // OK, C::i visible in B and hides A::i
        }
      }
      // more (irrelevant) stuff
    }
     

-end example]

在您的情况下, using-directive ns1中的名称引入它出现的公共祖先命名空间和ns1的名称,意味着全局命名空间。 ns2内引入它们,因此ns2::foo的声明隐藏了ns1::foo的声明。

如果您希望找到ns1::foo,请改用使用声明。

void bar()
{
    using ::ns1::foo;
    foo(42);
}