根据this question,在using
指令之后定义类方法是有效的,而不是将它们包含在namespace
块中。
然而,普通功能似乎并非如此。考虑:
Greeting.hh
#pragma once
namespace NS
{
class Greeting
{
public:
void hello();
};
void otherHello();
}
Greeting.cc
#include "Greeting.hh"
#include <iostream>
using namespace NS;
void Greeting::hello()
{
std::cout << "Greeting::hello" << std::endl;
}
void otherHello()
{
std::cout << "otherHello" << std::endl;
}
main.cc
#include "Greeting.hh"
int main()
{
NS::Greeting o;
o.hello();
NS::otherHello();
}
这不会编译,产生以下错误消息:
undefined reference to `NS::otherHello()'
进一步检查表明otherHello
的符号前面没有命名空间,而Greeting::hello
&#39; s是:
g++ -std=c++14 -pedantic -Wall -c Greeting.cc
nm -C Greeting.o | grep T
000000000000002a T otherHello()
0000000000000000 T NS::Greeting::hello()
这是否与accepted answer的标准参考相矛盾?
&#34;在非限定名称查找(3.4.1)期间,名称显示为好像 在包含两者的最近的封闭命名空间中声明 using-directive和指定的命名空间。&#34;
答案 0 :(得分:6)
重要的是要记住
声明的封闭名称空间是其中的名称空间 声明词汇出现,除了重新声明 在其原始命名空间之外的命名空间成员(例如,定义 在[namespace.memdef]中指定。这种重新宣布也是一样的 将名称空间封闭为原始声明。
让我们看看otherHello
定义。词汇在哪里出现?当然,在全局命名空间中。这也是宣言的重点。这意味着封闭的命名空间是全局命名空间,最终会得到::otherHello
的声明。
所以不,这与另一个问题的接受答案的标准引用并不矛盾。成员函数可以在类之外定义,只要它们通过类名([class.mfct/4])限定:
如果成员函数的定义在词法之外是词法上的 定义,成员函数名称应由其类限定 使用::运算符命名。
所以我们只需要询问,Greeting
是否将同一个类命名为NS::Greeting
?为什么,是的。 using指令对此负责。
我将添加此细分以期澄清。请考虑以下代码段:
namespace NS1 {
namespace NS2 {
void hello();
}
}
using namespace NS1;
void NS2::hello() {
}
int main() {
NS1::NS2::hello();
return 0;
}
当编译器遇到NS2::hello
被定义时,它会预先为该声明符id进行名称查找。根据{{3}}:
在declarator-id为qualified-id,名称的声明中 在声明的qualified-id被查找之前使用 定义命名空间范围;查看qualified-id后面的名称 在成员的类或命名空间的范围内。
因此在定义范围(全局范围)中查找NS2
,并根据您引用的非限定名称查找规则,找到并解析为NS1::NS2
。这就是NS2::hello
与NS1::NS2::hello
相关联并解决为定义它的方式。
在OP的全局命名空间中,otherHello
之前没有任何内容。因此,不会发生名称查找。它立即在封闭的命名空间中定义了该函数,正如我之前所引用的那样。