【问题标题】:Does using namespace cause name hiding?使用命名空间会导致名称隐藏吗?
【发布时间】:2012-05-31 06:28:11
【问题描述】:

考虑以下代码:

namespace C {
    class X {};
}

namespace A {
    class X {};

    namespace B {
        using namespace C;

        X x;
    }
}

由于 using namespace 指令,我原本期望 x 的类型为 C::X,但 VS2010 和在线 LLVM/Clang 编译器都可以解析命名空间B 中的XA::X。使用 using 声明 (using C::X) 更改 using 指令,然后它会按预期解析为 C::X

标准说明使用指令 [7.3.4.2]:

using-directive 指定指定命名空间中的名称可以在 using-directive 出现在 using-directive 之后的范围内使用。在非限定名称查找 (3.4.1) 期间,名称看起来好像它们是在最近的封闭命名空间中声明的,其中包含使用指令和指定命名空间。

我对此的理解是C::X 应该看起来好像在命名空间B 中声明,有效地隐藏A::X。使用指令和使用声明之间的这种不一致是标准的哪些部分背后的原因?有没有办法通过 using 指令从外部范围隐藏名称?

【问题讨论】:

  • 也许线索就在名字看起来好像它们是在最近的封闭命名空间中声明的,其中包含两个使用指令和指定的命名空间。那不是::吗?如果是这样,是否首先找不到A::X(查找从内部命名空间向外)...虽然不确定,但 g++ 确实也拾取A::X,所以它非常一致跨编译器。
  • @David Rodríguez - dribeas:哦,这可以解释...

标签: c++ namespaces language-lawyer


【解决方案1】:

关于使用指令的章节似乎以某种方式清楚地表明您正在看到预期的行为:

7.3.4p2 using-directive 指定指定命名空间中的名称可以在 using-directive 出现在 using-directive 之后的范围内使用。在非限定名称查找 (3.4.1) 期间,名称看起来好像它们是在最近的封闭命名空间中声明的,其中包含 both 使用指令和指定命名空间。

7.3.4p3 using 指令不会将任何成员添加到它出现的声明区域。

using-directive将命名空间的成员添加到指令的公共命名空间祖先和使用的命名空间的查找集中,而不是直接添加到所在的范围使用指令。这在第二个引用中明确说明:它不会将任何成员添加到 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
    }

最后一个示例用于阐明传递性(并包含更多代码),但实际上它等同于您删除额外代码后的代码。

因此,在您的情况下,using-directive 似乎没有隐藏,而是被隐藏了。

【讨论】:

  • 所以对于我的第二个问题,我假设可以通过使用指令来隐藏名称,但前提是它们位于公共命名空间祖先的外部范围内。
  • 我会这么说。无论如何,我会完全避免using-directives,并且很少使用using-declarations。查找变得更加复杂,并且更难确定确切使用的内容,定义的位置...如果您需要扁平化复杂嵌套命名空间的使用,请考虑命名空间别名。跨度>
  • 我避免在我的真实代码中使用 using-directives,这只是试图通过利用名称查找规则来“查找类所在的位置”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-09
  • 2021-11-10
  • 2016-11-06
  • 1970-01-01
  • 1970-01-01
  • 2014-05-09
相关资源
最近更新 更多