使用指令与使用声明 [英] Using directive vs using declaration
问题描述
您能解释一下为什么此代码有效并打印16吗?
Can you explain why this code works and prints 16;
#include <iostream>
namespace X {
int p = 5;
}
namespace Y {
int p = 16;
using namespace X;
}
int main()
{
std::cout << Y::p;
}
以及此代码为何引发多重声明错误
and why this code throws error of multiple declaration
#include <iostream>
namespace X {
int p = 5;
}
namespace Y {
int p = 16;
using X::p;
}
int main()
{
std::cout << Y::p;
}
我听说using指令不仅仅是使用任何名称的声明的过程,因为它的工作方式似乎有所不同
I have heard that using directive isn't simply the process of using declaration of any name, as it seems to work differently
但是我不明白为什么,你能给出一些详细的解释吗?
But I can't understand why, could you give some detailed explanation ??
类似地,这可以很好地打印16,如果我仅使用X :: p的声明替换指令,则会抛出相同的错误
similarly this one works fine printing 16, if I replace using the directive with just the declaration of X::p it will throw the same error
#include <iostream>
namespace X {
int p = 5;
}
int p = 16;
using namespace X;
int main()
{
std::cout << ::p;
std::cout << "\n";
return 0;
}
推荐答案
关键区别在于using声明是一个声明.而using指令则不是.我知道这听起来很愚蠢,但这就是差异的本质.前者实际上是在声明性区域中添加声明,而后者仅使某些名称在声明性区域中可用.
The key difference is that a using declaration is, well, a declaration. While a using directive is not. Sounds stupid, I know, but that's the nature of the difference. The former actually adds declarations to a declarative region, while the latter only makes certain names usable in a declarative region.
使名称在声明的范围内可使用,而不是进行声明,这是一件很薄弱的事情.如果存在另一个具有相同名称的声明,例如
Making a name usable in a certain scope, as opposed to declaring it, is intended to be a much weaker thing. The former is not considered during qualified lookup, if there's another declaration with the same name, as [basic.scope.hiding]/4 says:
在查找由名称空间名称限定的名称时, 否则将由 using-directive 使声明可见的声明 可以被名称空间中具有相同名称的声明隐藏 包含 using-directive
During the lookup of a name qualified by a namespace name, declarations that would otherwise be made visible by a using-directive can be hidden by declarations with the same name in the namespace containing the using-directive
这几乎解释了您的第一个代码段.由于使用了声明,因此有了该名称的声明,因此不考虑使用指令中可见的名称.不管先到是谁,声明总是更强.
And that pretty much explains your first code snippet. There's a declaration for that name, on account of the using declaration, so the name made visible by the using directive isn't considered. Doesn't matter which comes first, a declaration is always stronger.
您的第二个代码段在Y
中为p
提供了两个声明.当涉及到这些时,通常适用于声明的规则.第二个必须声明相同的内容,否则程序格式错误.没什么,真的.
Your second code snippet has two declarations for p
in Y
. And when it comes to those, the usual rules for declarations apply. The second one must declare the same thing, or the program is ill-formed. Nothing more to it, really.
最后,在您的第三个代码段中,与第一个代码段中的内容更多相同. [basic.lookup.qual]/4 这样说:
Finally, in your third code snippet, it's more of the same as in your first code snippet. [basic.lookup.qual]/4 says this:
由一元作用域运算符
::
([expr.prim])前缀的名称是 在使用它的翻译单位的全球范围内查找. 该名称应在全局名称空间范围内声明,或为 由于以下原因其声明在全局范围内可见的名称 using-directive ([namespace.qual]).使用::
即使其标识符已隐藏也要引用的名称.
A name prefixed by the unary scope operator
::
([expr.prim]) is looked up in global scope, in the translation unit where it is used. The name shall be declared in global namespace scope or shall be a name whose declaration is visible in global scope because of a using-directive ([namespace.qual]). The use of::
allows a global name to be referred to even if its identifier has been hidden.
因此,除了要查找的名称空间之外,其他所有内容都与您的第一个示例类似.你们都声明了它,并通过using指令使其可用.我引用的第一段决定了必须选择的段.
So other than the namespace being looked up, everything else is just like your first example. You both declare it, and make it available by the using directive. The first paragraph I quoted determines which one must be picked.
这篇关于使用指令与使用声明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!