下面是示例代码
#include <iostream>
using namespace std;
namespace A {
void f() { cout << "a" << endl; }
}
namespace B {
void f() { cout << "b" << endl; }
}
namespace C {
using namespace A;
using namespace B;
using A::f;
}
namespace D {
using A::f;
using namespace A;
using namespace B;
}
int main()
{
C::f();
D::f();
}
当我在Visual Studio 2015中尝试时,这会打印两次“ a”,此行为是由标准定义的还是此实现特定的?
答案 0 :(得分:4)
cppreference.com中的以下两段应解释该行为:
使用指令[
using namespace A;
]不会在显示区域中添加任何名称(与使用声明[using A::f;
]不同),因此不会阻止使用相同的名称宣布。使用指令是可传递的,用于无条件查找:如果范围包含指定名称空间名称的使用指令,而名称空间本身包含某些名称空间2的using指令,则效果就好像第二个名称空间中的using指令出现在第一个名称空间中。这些可传递名称空间的出现顺序不会影响名称查找。
简单地说:using A::f;
就像您在此命名空间中声明该函数一样。 using namespace A;
只会导致类型名称查找的行为就像您的情况下的当前名称空间(C
或D
)是A
中的名称空间一样。
这类似于
namespace A {
void f() { cout << "a" << endl; }
namespace B {
void f() { cout << "b" << endl; }
}
}
和
namespace A {
namespace B {
void f() { cout << "b" << endl; }
}
void f() { cout << "a" << endl; }
}
等效。
答案 1 :(得分:4)
它是由标准定义的(诸如此类的东西总是如此)。要意识到的关键是,您的各个using namespace
行对您的程序没有任何影响。
using namespace Foo
是一个“使用指令”,它会影响范围内的代码执行的名称查找。也就是说,如果您的namespace C {}
块中的某个更高版本的函数试图找到名为foo
的对象,则A
和B
将会是编译器将搜索的位置。 foo
。相反,如果以后的代码引用C::foo
,则不会改变编译器的外观。单个块中两个连续using namespace
的顺序无关紧要,因为每个直到块末尾都具有完全的作用。
您能够在f
或C
中找到D
的原因是“使用声明” using A::f
。与使用指令不同,使用声明具有将名称注入范围的作用,以便其他代码可以将该名称引用在该范围内。