提问人:Igor G 提问时间:7/4/2019 最后编辑:StoryTeller - Unslander MonicaIgor G 更新时间:7/4/2019 访问量:1003
在其命名空间外部定义的类成员函数
Class member function defined outside its namespace
问:
以下代码与 godbolt 在线编译器资源管理器站点上提供的最新 MSVC、GCC 和 CLang 完美编译。我想知道为什么:
namespace ns
{
struct Test
{
void foo();
};
}
using namespace ns;
// Alert! Member function defined outside its namespace!
void Test::foo()
{
}
int main()
{
ns::Test obj;
obj.foo();
return 0;
}
CPPlusion 声明,如果成员函数在其类外部定义,则必须在该类的命名空间中定义该函数。请参阅有关成员函数的 cppreference 页面的最顶部。
但是,编译器仍然接受代码。这三个独立的编译器都不太可能有相同的错误,对吧?那么,他们接受这样的代码背后有充分的理由吗?
答:
5) using-directive:从在 using 指令之后对任何名称进行非限定名称查找的角度来看,直到它出现的范围结束,ns_name 中的每个名称都是可见的,就好像它是在包含 using 指令和 ns_name 的最近封闭命名空间中声明的一样。
这意味着在当前范围内,可以从该命名空间内的寻址中省略某些内容。ns
因此,当您编写以下代码时:
using namespace std;
vector<string> vectorofstrings;
你不必写
std::vector<std::string> vectorofstrings;
of a class 是类的名称。因此,如果您有:namespace
namespace aNamespace{
class aClass{
int aMember;
void aFunction();
};
}
然后,完全限定查找是,并且必须将函数定义为::aNamespace::aClass
void ::aNamespace::aClass::aFunction(){}
评论
::ns::Test
::ns::Test::foo
引用 C++ 17 (n4659) 12.2.1 [class.mfct]/1:
出现在类定义之外的成员函数定义 应出现在包含类定义的命名空间作用域中。
这意味着它必须在包含类的命名空间或该命名空间的任何父命名空间中定义。在你的例子中,它是在全局命名空间中定义的,它确实(间接)包含了类定义。
评论
12.2.1 成员函数 [class.mfct]
成员函数可以在其类定义中定义 (11.4),在这种情况下,它是一个内联成员函数 (10.1.6),或者如果已声明但未在其类定义中定义,则可以在其类定义之外定义。出现在类定义之外的成员函数定义应出现在包含类定义的命名空间作用域中。
这并不意味着定义必须出现在紧邻的范围内。它可以出现在任何封闭的命名空间中,即使它向上有几层。
但是,这将是非法的:
namespace a {
struct X {
void Y();
};
}
namespace b { // not an enclosing namespace
void X::Y()
{
std::cout << "Do a thing!\n";
}
}
评论
struct X
namespace b
X::Y
b::X::Y
struct X
namespace b
评论
using namespace ns;
using namespace ns;
表示可以预置到以下作用域中的任何函数/变量之前ns::