使用指令与使用声明

时间:2018-01-20 13:45:35

标签: c++ scope namespaces using

你能解释为什么这段代码有效并打印16;

#include <iostream>

namespace X {
int  p = 5;
}
namespace Y {
int  p = 16;

using namespace X;
}

int main()
{
std::cout << Y::p;
}

以及为什么此代码会抛出多次声明的错误

#include <iostream>

namespace X {
int  p = 5;
}
namespace Y {
int  p = 16;

using X::p;
}

int main()
{
std::cout << Y::p;
}

我听说使用指令并不是简单地使用任何名称声明的过程,因为它似乎工作方式不同

但是我无法理解为什么,你能给出一些详细的解释吗?

类似这一个工作精细打印16,如果我使用指令替换只是X :: p的声明它会抛出相同的错误

 #include <iostream>

namespace X {
    int  p = 5;
}

int  p = 16;

using namespace X;

int main()
{
    std::cout << ::p;
    std::cout << "\n";

    return 0;
}

1 个答案:

答案 0 :(得分:4)

关键的区别在于使用声明是一个声明。虽然使用指令不是。听起来很愚蠢,我知道,但这就是差异的本质。前者实际上将声明添加到声明性区域,而后者仅使某些名称在声明性区域中可用。

使名称在某个范围内可用,而不是声明它,意图是一个更弱的东西。如果有另一个具有相同名称的声明,[basic.scope.hiding]/4说:

,则在限定查询期间不考虑前者
  

在查找由命名空间名称限定的名称期间,   否则将由 using-directive 显示的声明   可以通过命名空间中具有相同名称的声明隐藏   包含 using-directive

这几乎解释了您的第一个代码段。由于使用声明,该名称有声明,因此不考虑using指令可见的名称。首先出现的问题并不重要,声明总是更强。

您的第二个代码段在p中有两个Y声明。当涉及到这些时,通常的声明规则适用。第二个必须声明相同的事情,或者程序是不正确的。没什么,真的。

最后,在您的第三个代码段中,它与您的第一个代码段中的内容更相似。 [basic.lookup.qual]/4说:

  

以一元范围运算符::​([expr.prim])为前缀的名称是   在全球范围内,在使用它的翻译单元中查找。   名称应在全局命名空间范围内声明,或者应为a   由于a,其声明在全局范围内可见的名称    using-directive ([namespace.qual])。 ​::的使用允许全球化   即使其标识符已被隐藏,也要引用的名称。

除了查找名称空间之外,其他一切就像你的第一个例子。你们都声明它,并通过using指令使它可用。我引用的第一段确定必须选择哪一个。