访问全局变量和命名空间变量

Accessing a global and namespace variable

提问人:BethBorgov 提问时间:1/14/2021 最后编辑:BethBorgov 更新时间:1/14/2021 访问量:584

问:

我正在尝试使用以下代码中的 using 指令访问变量 x:

#include <iostream>
using namespace std;
int x = 10;
namespace e {
int x = 5;
}
int main() {
using namespace e; // Because of this line compiler shows error
cout << x;
return 0;
}

通常,我们使用以下行来访问 x,但我收到错误 我们也可以使用 e::x;但我的问题是为什么我们不能使用命名空间 e;

C++ 命名空间 using 指令

评论

1赞 Yksisarvinen 1/14/2021
请注意,错误不在您指出的行上,而是在下面的行上。如果有,编译器如何区分 和 ?using namespace e;::x::e::x
0赞 BethBorgov 1/14/2021
你能解释清楚,因为我是第一次学习这个话题吗?
0赞 Federico Baù 1/14/2021
这回答了你的问题吗?为什么以及如何在 C++ 中使用命名空间?
0赞 Federico Baù 1/14/2021
这 2 个答案可能会对您有所帮助!: 为什么以及如何在 C++ 中使用命名空间? & 命名空间到底是什么,为什么有必要
0赞 BethBorgov 1/14/2021
我不这么认为

答:

1赞 user7860670 1/14/2021 #1

在此示例中,似乎使命名空间中的名称在函数范围内可用。但是,它不会这样做。相反,它尝试将名称(在未确定的查找期间)从最近的封闭命名空间 和 注入到全局命名空间。因此变得模棱两可。using namespace e;emainmainnamespace emainnamespace ex

评论

0赞 BethBorgov 1/14/2021
你能用简单的词解释一下吗?
0赞 user7860670 1/14/2021
@BethBorgov使编译器在全局命名空间旁边搜索名称,就好像在全局命名空间旁边声明了 from 命名空间一样。using namespace e;xmainxeint x = 10;
0赞 Yksisarvinen 1/14/2021 #2

让我们从另一个例子开始。

const int x = 10;

namespace e {
const int y = 5;
}

int main()
{
std::cout << e::y;
using namespace e;
std::cout << y;
}

全局命名空间中有值为 10 且名称为 name 的变量(可以简称为)和值为 5 且名称位于命名空间中的变量(必须称为 )。xxyee::y

通过添加 ,可以命名空间中的所有名称注入到全局命名空间中。这意味着全局命名空间现在包含 names 和 ,而命名空间包含 name 。现在,您可以使用 和 来引用具有 value 的变量。using namespace e;exyey5ye::y

现在,回到你的例子。如果我们改为:yx

const int x = 10;

namespace e {
const int x = 5;
}

int main()
{
std::cout << e::x;
using namespace e;
std::cout << x;
}

有 in 全局命名空间 和 in 命名空间 。通过添加,您将命名空间中的所有名称注入到全局命名空间,因此现在全局命名空间包含名称 和 ,而命名空间包含名称 。看到问题了吗?全局命名空间包含两个名称,这会使编译器感到困惑。当您尝试在 name 下打印变量时,编译器在全局命名空间中查找名称并找到两个 .它无法选择您的意思是哪一个,因此它会抛出错误。xxeusing namespace e;exxexxxx

这就是为什么使用命名空间(特别是使用命名空间 std;)被认为是邪恶的主要原因。人们可以通过更新库或引入新函数来轻松破坏工作代码。在这种情况下,编译器错误是最好的结果,但有时编译器可能会默默地将一个函数替换为另一个函数,因为它匹配得更好。

您仍然可以使用完全限定名称访问这两个变量:

int main()
{
using namespace e;
std::cout << ::x << " "; //x from global with fully quafilied name
std::cout << ::e::x << " "; //x from namespace e with fully qualified name
std::cout << e::x; //not fully qualified, but not ambiguous either - only one x in namespace e
}