C++:使用声明和指令的顺序会影响选择吗?

C++: Does the order of using declaration and directive affect the selection?

下面是示例代码

#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" 两次,这种行为是由标准定义的还是特定于此实现的?

cppreference.com 中的以下两段应该解释该行为:

Using-directive [using namespace A;] does not add any names to the declarative region in which it appears (unlike the using-declaration [using A::f;]), and thus does not prevent identical names from being declared.

Using-directives are transitive for the purposes of unqualified lookup: if a scope contains a using-directive that nominates a namespace-name, which itself contains using-directive for some namespace-name-2, the effect is as if the using directives from the second namespace appear within the first. The order in which these transitive namespaces occur does not influence name lookup.

简单地说:using A::f;就好像你在这个命名空间中声明了函数。 using namespace A; 只会导致类型名查找的行为就好像当前命名空间(CD)在您的例子中是 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; }
}

是等价的。

它是由标准定义的(像这样的东西总是这样)。要意识到的关键是,您的各种 using namespace 行对您的程序没有任何影响。

using namespace Foo 是一个 "using directive",它会影响范围内代码执行的名称查找。也就是说,如果您的 namespace C {} 块中的某些后续函数试图找到某个名为 foo 的对象,则 AB 将位于编译器将搜索的位置中一个foo。相反,如果后面的代码引用 C::foo,它不会改变编译器查找的位置。单个块中两个连续 using namespace 的顺序无关紧要,因为每个块都具有完整的效果,直到块结束。

您能够在 CD 中找到 f 的原因是 "using declaration" using A::f。与 using 指令不同,using 声明具有将名称注入范围的效果,这样其他代码就可以在该范围内引用该名称。