根据这个问题,在using指令之后定义类方法是有效的,而不是将它们包含在namespace块中.
但是,普通功能似乎并非如此.考虑:
Greeting.hh#pragma once
namespace NS
{
class Greeting
{
public:
void hello();
};
void otherHello();
}
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)
main.cc#include "Greeting.hh"
int main()
{
NS::Greeting o;
o.hello();
NS::otherHello();
}
Run Code Online (Sandbox Code Playgroud)
这将无法编译,产生以下错误消息:
undefined reference to `NS::otherHello()'
Run Code Online (Sandbox Code Playgroud)
进一步检查表明,otherHello符号前面没有命名空间,而Greeting::hellos是:
g++ -std=c++14 -pedantic -Wall -c Greeting.cc
nm -C Greeting.o | grep T
000000000000002a T otherHello()
0000000000000000 T NS::Greeting::hello()
Run Code Online (Sandbox Code Playgroud)
这与接受的答案中的标准参考是否相矛盾?
"在非限定名称查找(3.4.1)期间,名称看起来好像是在最近的封闭命名空间中声明的,其中包含using-directive和指定的命名空间."
重要的是要记住这一点
声明的封闭名称空间是声明词汇表中出现的名称空间,除了在其原始名称空间之外重新声明名称空间成员(例如,[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;
}
Run Code Online (Sandbox Code Playgroud)
当编译器遇到NS2::hello被定义时,它会预先为该声明符id进行名称查找.根据[basic.lookup.qual/3]:
在declarator-id是qualified-id的声明中,在声明的qualified-id 之前使用的名称在定义的命名空间范围中被查找 ; 在成员的类或命名空间的范围内查找qualified-id后面的名称.
因此NS2,在定义范围(全局范围)中查找,并根据您引用的非限定名称查找规则,找到并解析为NS1::NS2.这NS2::hello就是NS1::NS2::hello定义它的方式和解决方法.
在OP的全局命名空间中,otherHello前面没有任何内容.因此,不会发生名称查找.它正如我之前引用的那样立即在封闭命名空间中定义该函数.
| 归档时间: |
|
| 查看次数: |
235 次 |
| 最近记录: |