理解C++中的命名空间作用域

5

当我运行下面的代码片段时,输出结果是a is 6。但是由于我使用了命名空间n1,其中也有一个叫做“a”的变量,所以输出结果不应该是a is 5吗?我错过了什么吗?

#include <iostream>

using namespace std;

namespace n1{
    int a = 5;
}

int main(void){
    int a = 6;
    using namespace n1;
    cout<<"a is "<<a<<endl;
    return 0;
}

但是如果我在cout中使用完全限定名称,即cout<<"a is "<<n1::a;,输出结果如预期的那样为5。那么使用命名空间的目的是什么?


你的 a 是 main 函数的本地变量。你必须使用 n1::a - user1810087
3个回答

5
using指令是编译器搜索名称a的地方的提示。
这样,名称查找将按照以下顺序进行:
  • 首先在本地作用域中查找a
  • 如果未发现a,则在命名空间n1中查找
  • 如果仍然未找到a,则在全局命名空间中查找
如果没有提供using指令,则不会执行第二步。
在您的情况下,由于实际上有一个变量(但它可能是任何东西,我们谈论的是名称)命名为a,因此不会进一步进行查找。

但是,如果将a定义为全局变量而不是局部变量,并且还在命名空间中定义了它,编译器会标记错误,指出“a不明确”。但根据上述规则,应该优先考虑在命名空间中定义的变量a,而不是全局范围内的变量。 - niting112
嗯?当我尝试一个非常简单的例子时,我没有收到这样的消息...(将a声明和定义为全局变量,在命名空间中以及在主作用域中)。 - JBL
可能这取决于编译器。我正在使用Visual Studio 2010。你用的是哪个? - niting112
这段代码在win32-msvc2012上编译、运行并表现如预期。 - JBL

3
规则很简单:
"本地变量始终会遮盖其他命名空间或具有相同名称的全局变量。" 在声明局部变量 a 的范围内,使用指令对符号名称 a 没有影响。它仍然在当前作用域内从命名空间 n1 导入所有符号名称,但是局部变量 a 仍然隐藏了 n1::a。因此,n1::a 简单地不可见,您需要使用完全限定名称。

但是如果我将变量a定义为全局变量而不是局部变量(但仍保留命名空间定义),编译器会报告“a”为歧义符号。因此,是命名空间或全局定义的变量彼此之间没有优先权吗? - niting112
@niting112:在这方面,只有本地变量被特殊处理。正如您所注意到的,在命名空间变量和全局变量的情况下,都没有得到特殊处理,因此会出现歧义错误。 - Alok Save

1
当一个变量在本地命名空间中被定义时(main函数中的a位于您的本地命名空间),它会优先使用它。
因此,在这种情况下,您必须告诉它(我想要来自n1命名空间的a:n1::a) 如果您删除a,则它将按预期工作...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接