【问题标题】:Using directive vs using declaration使用指令与使用声明
【发布时间】:2018-06-29 14:59:33
【问题描述】:

你能解释一下为什么这段代码可以工作并打印 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;
}

【问题讨论】:

    标签: c++ scope namespaces using


    【解决方案1】:

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

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

    在查找由命名空间名称限定的名称期间, using-directive 可以看到的声明 可以被命名空间中同名的声明隐藏 包含 using-directive

    这几乎解释了您的第一个代码 sn-p。由于 using 声明,该名称有一个声明,因此不考虑由 using 指令可见的名称。不管哪个先来,声明总是更强大。

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

    最后,在您的第三个代码 sn-p 中,它与您的第一个代码 sn-p 中的更多相同。 [basic.lookup.qual]/4 是这样说的:

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

    所以除了要查找的命名空间之外,其他一切都与您的第一个示例一样。你们都声明它,并通过 using 指令使其可用。我引用的第一段决定了必须选择哪一段。

    【讨论】:

    • 谢谢,我得到了所有这些,最后还有一个关于第三个示例的问题,当我删除 :: 运算符并尝试仅打印 p 时,它会向我抛出错误它需要声明并打印 16 吗?
    • 它说 p 是模棱两可的
    • 为什么声明不包含指令?
    • @HovhannesVardanyan - 请注意,我引用的段落与 qualified 名称查找有关。 IE。 ns_name::something::something。对于 unqualified 查找,由 using 指令指定的名称被视为封闭命名空间的成员。所以你会有一个模棱两可的地方。
    猜你喜欢
    • 2013-04-15
    • 1970-01-01
    • 2017-09-21
    • 2020-09-21
    • 1970-01-01
    • 2014-01-20
    • 2022-08-16
    • 1970-01-01
    相关资源
    最近更新 更多