我是命名空间的新手,并且正在尝试使用C++ Primer
#include<iostream>
namespace Jill
{
double bucket;
double fetch;
struct Hill{ };
}
double fetch;
int main()
{
using namespace Jill;
Hill Thrill;
double water = bucket;
//double fetch; //<<<<<<<<<<<<//
std::cin>> fetch;
std::cin>> ::fetch;
std::cin>> Jill::fetch;
std::cout<<"fetch is "<<fetch;
std::cout<<"::fetch is "<< ::fetch;
std::cout<<"Jill::fetch is "<< Jill::fetch;
}
int foom()
{
Jill::Hill top;
Jill::Hill crest;
}
Run Code Online (Sandbox Code Playgroud)
当标记的行//<<<<<<<<<<<<//未注释时,我得到预期的结果.即
local变量隐藏global和Jill::fetch.但是当我发表评论时,剩下2个.global fetch和Jill::fetch.编译器会给出错误
namespaceTrial1.cpp:17:13: error: reference to ‘fetch’ is ambiguous
namespaceTrial1.cpp:9:8: error: candidates are: double fetch
namespaceTrial1.cpp:5:9: error: double Jill::fetch
namespaceTrial1.cpp:20:26: error: reference to ‘fetch’ is ambiguous
namespaceTrial1.cpp:9:8: error: candidates are: double fetch
namespaceTrial1.cpp:5:9: error: double Jill::fetch
Run Code Online (Sandbox Code Playgroud)
我的问题是为什么编译器会混淆这导致歧义?为什么它不承担fetch刚才Jill::fetch,因为我已经添加using namespace Jill在开始main()
如果我using Jill::fetch;在main的开头使用声明,问题就会得到解决.因为using Jill::fetch它就好像它已在该位置声明一样.所以,它就像有一个local fetch变量.[我是否正确?]为什么using declaration表现得好像变量是在该位置声明的并且using directive不是?
using 指令修改名称查找的方式对于大多数程序员来说并不完全直观。标准在 [namespace.udir]p2 中这样说:
在非限定名称查找 (3.4.1) 期间,名称看起来就像是在最近的封闭命名空间中声明的,该命名空间同时包含 using 指令和指定命名空间。
这种措辞意味着命名空间中的名称不会出现在当前作用域中,而是出现在某些外部作用域中。在您的示例中,using 指令位于全局命名空间中的函数中,而 Jill 也位于全局命名空间中,因此 Jill 中的名称看起来就像位于全局命名空间中一样。(正如 Joachim 所说,这些名称实际上并未在那里引入,因此它们不会立即与现有名称冲突,并且当您实际使用它们时,您只会得到不明确的查找。)
这是一个简单的情况,编译器会给出一个错误,这很好。实际上可能会变得更复杂。
namespace Outer {
namespace Mid1 { int i = 1; }
namespace Mid2 {
namespace Tricky {
int i = 2;
namespace Inner {
void f() {
using namespace Mid1;
std::cout << i;
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
即使您在引用 i 的行旁边有 using 指令,这也会输出 2,而不是 1。Mid1但包含两者和 using 指令的最近的封闭命名空间是Outer,因此Mid1::i其行为就好像它是在 中声明的一样Outer。如果你有一个,Outer::i它就会被 遮蔽Tricky::i,而且Mid1::i票价也好不到哪里去。
一个简单的解决方案是禁止 using 指令并仅使用 using 声明和命名空间别名。它们更加直观。