using 指令如何以及在何处注入成员名称?

How and where using directive injects member names?

据我所知,using 指令在最近的封闭命名空间中公开或注入命名空间的所有名称。这是来自 C++ primer:

In contrast, a using directive makes the entire contents of a namespace available In general, a namespace might include definitions that cannot appear in a local scope. As a consequence, a using directive is treated as if it appeared in the nearest enclosing namespace scope.

In the simplest case, assume we have a namespace A and a function f, both defined at global scope. If f has a using directive for A, then in f it will be as if the names in A appeared in the global scope prior to the definition of f

并且来自 cppreference:

  1. using-directive: From the point of view of unqualified name lookup of any name after a using-directive and until the end of the scope in which it appears, every name from ns_name is visible as if it were declared in the nearest enclosing namespace which contains both the using-directive and ns_name.
#include <iostream>

int x = 1;
int y = 2;
int z = 3;

namespace A{
    namespace B{
        int x = 5;
        int y = 10;
        int z = 0;
    }
    void foo(){
        using namespace A::B;
        std::cout << x << '\t' << y << '\t' << z << '\n'; // x, y, z are not ambiguous
    }
}

namespace AA{
    namespace BB{
        void bar(){
            using namespace A::B;
            std::cout << x << '\t' << y << '\t' << z << '\n'; // x, y, z are ambiguous
        }
    }
}


int main(){

    A::foo(); // works fine
    AA::BB::bar(); // fails to compile

    std::cout << "\ndone!\n";
}

是的,这很令人费解,但是您提供的引述准确地解释了正在发生的事情。在你的第一个例子中(变量数量减少到 1):

int x = 1;

namespace A {
    namespace B {
        int x = 5;
    }
    void foo(){
        using namespace A::B;
        std::cout << x << '\n';
    }
}

最近的命名空间是 A。本质上,代码等同于

int x = 1;

namespace A {
    int x = 5;

    void foo(){
        std::cout << x << '\n'; // x from NS a.
    }
}

x 将是 A 中定义的名称并将被使用。

在第二个例子中,

namespace AA {
    namespace BB {
        void bar() {
            using namespace A::B;
            std::cout << x << '\n'; 
        }
    }
}

最近的命名空间是全局命名空间。本质上,代码等同于

int x = 1;
int x = 5;

namespace AA {
    namespace BB {
        void bar() {
            std::cout << x << '\n'; 
        }
    }
}

此代码格式不正确,因为 x 无法在同一范围内重新定义。