备注①:name:符号。指的实体包括:变量、函数、类

备注②:认为全局命名空间也是一个包,在此称作 ROOT:: 或 global::

(这样就有了两个特别的包:一个是全局包,一个是std包。但对于编译器(pack-path. names模型)来说,它们和用户自定义的namespace没有区别)


修正1. global::(全局包)中的names,并不都是用户自定义的。

经实验验证,修正对using namespace std的认识-LMLPHP

2.   两条重要认识,以及由此解释一些之前的问题

一、using namespace xxx; <—> using pack-A的本质作用:   相当于把 导入的Pack-A的 names 移到 using pack-A;  这行文字所在的那个namespace   的names空间里。

二、所有非ROOT 的namespace里 ,都已默认存在 using namespace ::  (移入了ROOT包的 names ) ——>  所以才直接用全局的names

结论1:之前都是 "using namespace std "写在自定义namespace外,那么这行处在global::中,导致:把引进来的std::包里的names移到了 global包,成为全局的名字。

又因为各namespace已默认导入了global::names,所以这部分std::names进入了各namespace里。

导致的问题: 这样,当在wjh::内写某个name的定义时,若未加namespace-xxx::前缀而直接引用了 ‘fuck’,那么这个fuck可能有3处来源:

①wjh::fuck

②(global::) fuck

③namespace-ABC::fuck    //     在全局(=namespace外部) 中using namespace ABC后, ABC::下的names进入全局空间,进一步进入wjh::

只要以上3个namespace里存在不止一个 fuck 这个name,就属于 ‘Ambiguous function call’ 报错。 (也可能不报错,但编译器会自己挑一个合适的用!)

不存在什么优先认定,3个中只能存在1个!

     /*

*    ↑   修正:实验了一下,当不加包路径的 fuck存在上面①②③时,确实会选择①、编译器不提示报错。 所以同namespace的那个name确实是优先的

*         但当同namespace下无此name,②③是会冲突的。

*/

结论2:所以using namespace std; 为什么不能使用?

别人的模块引用了你的这个头文件后,多了这行字,原来未加namespace:: 引用的name只有一处定义,现在可能就多了个定义,

而编译器又不报错,就导致‘God knows what’种种奇特行为(因为引用的name被偷偷替换掉了)


写段实验代码验证一下以上认识:

   前提:<test.h> :  定义一个global::fuckit();    在namespace wjh{ }里也定义一个fuckit(); 

观察:此时在wjh{ } 中引用 fuckit()  (不加wjh::),看是否提示

#ifndef _TRIAL_1_H
#define _TRIAL_1_H

int fuckit();

namespace wjh {
   int fuckit();
}
#endif

在global::下使用如下 (该main位于global空间)

(using namespace wjh;  把 wjh::fuckit 这个name移入了global::中)

#include "trial-1.h"

using namespace wjh;

int main() {
::fuckit();
wjh::fuckit();
fuckit(); //报错! system("pause");
return ;
}

截图如下:

经实验验证,修正对using namespace std的认识-LMLPHP


更进一步的实验:

 #ifndef _TRIAL_1_H
#define _TRIAL_1_H // ③ s_t_d::fuckit
namespace s_t_d {
int fuckit();
} // ② (global::) fuckit
int fuckit(); // ① wjh::fuckit
namespace wjh {
using namespace s_t_d;
int fuckit();
void call_fuckit();
} #endif
 #include "trial-1.h"

 #include <iostream>
#include <cstdlib> //using namespace s_t_d;
//using namespace wjh; int s_t_d::fuckit() {
std::cout << "s_t_d:: fuckit" << std::endl;
return ;
}
int fuckit() {
std::cout << "global:: fuckit" << std::endl;
return ;
}
int wjh::fuckit() {
std::cout << "wjh:: fuckit" << std::endl;
return ;
} void wjh::call_fuckit() {
using namespace s_t_d;
std::cout << "running in wjh:: calling fuckit ..." << std::endl;
fuckit();
} int main() {
wjh::call_fuckit(); fuckit(); system("pause");
return ;
}
05-27 16:27