我尝试在以下代码中使用
using
指令访问变量 x:
#include <iostream>
using namespace std;
int x = 10;
namespace e {
int x = 5;
}
int main() {
using namespace e; // Because of this line, the compiler shows an error
cout << x;
return 0;
}
一般来说,我们使用以下行来访问
x
,但我收到错误。
我们也可以使用
using e::x;
,但我的问题是为什么我们不能使用using namespace e;
。
在此示例中,
using namespace e;
似乎使命名空间 e
中的名称在 main
函数作用域中可用。然而它并没有这样做。相反,它尝试将名称(在 main
中进行非限定查找期间)从 namespace e
注入到最近的 main
和 namespace e
的封闭命名空间,即全局命名空间。因此 x
变得含糊不清。
让我们从另一个例子开始。
const int x = 10;
namespace e {
const int y = 5;
}
int main()
{
std::cout << e::y;
using namespace e;
std::cout << y;
}
全局命名空间(可以简称为
x
)中有值为10、名称为x
的变量,命名空间y
(必须简称为)中有值为5、名称为
e
的变量e::y
)。
通过添加
using namespace e;
,您可以将命名空间 e
中的所有名称注入到全局命名空间中。这意味着全局命名空间现在包含名称
x
和 y
,命名空间 e
包含名称 y
。您现在可以使用 5
和 y
来引用值为 e::y
的变量。
现在,回到你的例子。如果我们将
y
更改为 x
:
const int x = 10;
namespace e {
const int x = 5;
}
int main()
{
std::cout << e::x;
using namespace e;
std::cout << x;
}
全局命名空间中有
x
,命名空间 x
中有 e
。通过添加 using namespace e;
,您可以将命名空间 e
中的所有名称注入到全局命名空间中,因此现在全局命名空间包含名称 x
和 x
,命名空间 e
包含名称 x
。看到问题了吗?全局命名空间包含两个名称x
,这会让编译器感到困惑。当您尝试在名称 x
下打印变量时,编译器会在全局命名空间中查找名称并找到两个 x
。它无法选择您想要的那个,因此会抛出错误。
using namespace
(特别是using namespace 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
}