访问全局和命名空间变量

问题描述 投票:0回答:2

我尝试在以下代码中使用

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;

c++ namespaces using-directives
2个回答
1
投票

在此示例中,

using namespace e;
似乎使命名空间
e
中的名称在
main
函数作用域中可用。然而它并没有这样做。相反,它尝试将名称(在
main
中进行非限定查找期间)从
namespace e
注入到最近的
main
namespace e
的封闭命名空间,即全局命名空间。因此
x
变得含糊不清。


0
投票

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

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
}
© www.soinside.com 2019 - 2024. All rights reserved.