引用标准:
using-directive指定指定名称空间中的名称 可以在using指令出现的范围内使用 使用指令。在非限定名称查找(3.4.1)期间,名称 看起来好像是在最近的封闭命名空间中声明的 它包含using-directive和指定的命名空间。
看看这段代码:
namespace A {
int fn() { return 1; }
}
namespace Inner {
int fn() { return 2; }
namespace B {
using namespace A;
int z = fn();
}
}
在此之前,在我了解命名空间的确切规则之前,我曾预计z
将被初始化为1,因为我写了using namespace A
,因此预计会使用A::fn()
。但事实并非如此,z
将被初始化为2,因为Inner::fn()
因为我引用的规则而被调用。
这种行为背后的理由是什么:“好像它们是在最近的包含命名空间中声明的,它包含using-directive和指定的命名空间”?
如果using namespace
使用声明来处理该命名空间中的所有内容,那将是什么缺点?
注意:this是相关问题,促使我提出这个问题。
答案 0 :(得分:4)
命名空间系统的理想属性是我称之为增量API兼容性的属性。也就是说,如果我在命名空间中添加一个符号,那么任何以前工作的程序都应该继续工作并且意味着同样的事情。
现在,带有重载的普通C ++不是增量API兼容:
int foo(long x) { return 1; }
int main()
{
foo(0);
}
现在我添加了重载int foo(int x) { return 2; }
,程序会默默地改变意义。
无论如何,当C ++人员设计namespace
系统时,他们希望在递增外部API时,以前工作的代码不应该从选择符号的位置更改命名空间。从您的示例中,以前的工作代码将类似于:
namespace A {
//no fn here, yet
}
namespace Inner {
int fn() { return 2; }
namespace B {
using namespace A;
int z = fn();
}
}
z
很容易初始化为2
。现在使用名为A
的符号扩充名称空间fn
不会改变该工作代码的含义。
相反的情况并不适用:
namespace A {
int fn() { return 1; }
}
namespace Inner {
// no fn here
namespace B {
using namespace A;
int z = fn();
}
}
此处z
已初始化为1
。当然,如果我将fn
添加到Inner
,它将更改程序的含义,但Inner
不是外部API:实际上,最初编写Inner
时, A::fn
已经存在(它被称为!),所以没有理由不知道冲突。
想象一下这个C ++ 98程序:
#include <iostream>
namespace A {
int move = 0;
void foo()
{
using namespace std;
cout << move << endl;
return 0;
}
}
int main()
{
A::foo();
return 0;
}
现在,如果我使用C ++ 11编译它,由于这个using
规则,一切正常。如果using namespace std
使用声明来处理该命名空间中的所有内容,那么此程序将尝试打印函数std::move
而不是A::move
。