你能解释为什么这段代码有效并打印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;
}
答案 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指令使它可用。我引用的第一段确定必须选择哪一个。