是否可以在声明类成员的命名空间之外定义类成员?

Can class members be defined outside the namespace in which they are declared?

提问人:nriedlin 提问时间:8/7/2014 最后编辑:TemplateRexnriedlin 更新时间:8/7/2014 访问量:2071

问:

有时我会发现如下代码(实际上一些类向导会创建这样的代码):

// C.h
namespace NS {

class C {
    void f();
};

}

在实现文件中:

// C.cpp
#include "C.h"

using namespace NS;
void C::f() {
  //...
}

我尝试过的所有编译器都接受这种代码(gcc、clang、msvc compileonline.com)。让我感到不舒服的是.从我的角度来看,它存在于一个对位于命名空间 NS 中的对象具有无条件访问权限的环境中的全局命名空间中。但在编译者看来,生活在.正如我尝试过的所有编译器都同意这种观点一样,他们可能是对的,但是这种观点在标准中的哪个地方得到支持?using namespace NS;C::f()void C::f()namespace NS

C++ C++11 命名空间 language-lawyer using 指令

评论

0赞 Vaughn Cato 8/7/2014
居然住在课堂上.C::f()C

答:

15赞 TemplateRex 8/7/2014 #1

是的,语法确实是合法的,但不是,您的函数实际上确实存在于命名空间 NS 中。您看到的代码实际上等价于

namespace NS { void C::f() { /* ... } }

void NS::C::f() { /* ... */ }

这可能更类似于您习惯的。

由于 using 指令,您不仅可以在调用代码时省略 NS 部分,还可以省略其定义。标准有一个与您的代码匹配的示例(在粗体强调部分之后):

3.4.3.2 命名空间成员 [namespace.qual]

7 在命名空间成员的声明中,其中 declarator-id 是 qualified-id,因为命名空间的 qualified-id 成员的表单为 nested-name-specifier unqualified-id unqualified-id 应命名由 nested-name-specifier 或内联命名空间集的元素 (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

—结束示例 ] 但是,在此类命名空间成员声明中, nested-name-specifier 可能依赖于 using 指令来隐式地 提供 nested-name-specifier 的初始部分。[ 示例:

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)

—结束示例 ]

因此,您可以省略嵌套名称说明符的初始部分,但不能省略任何中间部分

评论

0赞 vpshastry 3/26/2022
这样做或这样做有什么好处?