使用指令与使用声明

Using directive vs using declaration

你能解释一下为什么这段代码有效并打印出 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;
}

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

但是我不明白为什么,能不能详细解释一下??

类似地,这个可以很好地打印 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;
}

主要区别在于 using 声明就是一个声明。而 using 指令不是。听起来很愚蠢,我知道,但这就是区别的本质。前者实际上是在声明区域中添加声明,而后者只是使某些名称在声明区域中可用。

使名称在特定范围内可用,而不是声明它,旨在成为一个更弱的事情。如果有另一个同名声明,则在限定查找期间不考虑前者,如 [basic.scope.hiding]/4 所说:

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

这几乎可以解释您的第一个代码片段。由于 using 声明,该名称有一个声明,因此不考虑通过 using 指令显示的名称。不管哪个先来,宣言总是更有力。

您的第二个代码片段在 Y 中有两个 p 的声明。当涉及到这些时,适用通常的声明规则。第二个必须声明相同的东西,否则程序格式错误。仅此而已,真的。

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

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 指令使其可用。我引用的第一段决定了必须选择哪一个。