有时候我会找到类似下面的代码(实际上有些类向导会创建这样的代码):
// C.h
namespace NS {
class C {
void f();
};
}
并在实施文件中:
// C.cpp
#include "C.h"
using namespace NS;
void C::f() {
//...
}
我尝试的所有编译器都接受这种代码(gcc,clang,msvc,compileonline.com)。让我感到不舒服的是using namespace NS;
。从我的观点来看,C::f()
存在于一个环境中,该环境对访问生命在命名空间NS中的对象具有不合格的访问权限。但是编译器的意见void C::f()
存在于namespace NS
中。正如我尝试的所有编译器分享这一观点一样,他们可能是正确的,但是在标准中这个观点的支持是什么?
答案 0 :(得分:14)
是的,语法确实合法,但不,您的功能确实存在于名称空间NS 中。您看到的代码实际上等同于
namespace NS { void C::f() { /* ... } }
或
void NS::C::f() { /* ... */ }
可能与您习惯的类似。
由于using指令,您不仅可以在调用代码时省略NS部分,还可以在其定义中省略NS部分。标准有一个与您的代码匹配的示例(在粗体强调部分之后):
3.4.3.2命名空间成员[namespace.qual]
7在声明者成员的声明中,声明者身份 是一个限定id,给定命名空间的qualified-id member的形式为nested-name-specifier unqualified-id unqualified-id应命名由。指定的命名空间的成员 嵌套名称说明符或内联命名空间集的元素 该命名空间的(7.3.1)。 [例如:
namespace A {
namespace B {
void f1(int);
}
using namespace B;
}
void A::f1(int){ } // ill-formed, f1 is not a member of A
-end example] 但是,在这样的命名空间成员声明中, 嵌套名称说明符可以依赖于使用指令 提供嵌套名称说明符的初始部分。 [示例:
namespace A {
namespace B {
void f1(int);
}
}
namespace C {
namespace D {
void f1(int);
}
}
using namespace A;
using namespace C::D;
void B::f1(int){ } // OK, defines A::B::f1(int)
-end example]
因此,您可以省略嵌套名称说明符的初始部分,但不是任何中间部分。