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

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

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


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

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 ;
}

截图如下:


更进一步的实验:

 #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 ;
}

经实验验证,修正对using namespace std的认识的更多相关文章

  1. using namespace std 和 using std::cin

    相较using std::cin使用using namespace std不会使得程序的效率变低,或者稳定性降低,只是这样作会将很多的名字引入程序,使得程序员使用的名字集合变小,容易引起命名冲突. 在 ...

  2. namespace std

    c++中使用namespace来防止命名冲突(重命名),我们经常使用的一些函数和变量都被放在一个叫std的namespace中,如标准I/O流操作,vector等等.我们在每一个文件中都可使用std中 ...

  3. C++ using namespace std(转载)

    转载自http://www.kuqin.com/language/20080107/3532.html 感谢这位大神的解答! 以下的内容摘抄自转载的文章里面的部分内容. 早些的实现将标准库功能定义在全 ...

  4. 不要在头文件中使用 using namespace std;

    不要在头文件中使用(using namespace std;).   若你使用了using namespace std;,在某一头文件中,那么包含这些头文件的文件就失去了"namespace ...

  5. using namespace std

    using namespace std std 是一个命名空间..不同的命名空间可以有相同的类名被定义 ..using namespace std;就是指明下面的程序使用std,如果不用这句指明的话就 ...

  6. #include<iostream.h>与#include<iostream> using namespace std的区别

    所谓namespace,是指标识符的各种可见范围.C++标准程序库中的所有标识符都被定义于一个名为std的namespace中.  一 :<iostream>和<iostream.h ...

  7. 关于using namespace std

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~关于using   namespace   std ~~~~~~~~~~~~~~~~~~~~~~~~~~~ ...

  8. 实验验证sys和system用户全库导出的区别

    我们在做逻辑数据泵全库导出的时候,有两种流行的写法,一种是sys用户导出,一种是使用system用户导出. 现在想知道二者之间有什么区别?实验验证之前不妨先思考一下: sys和system用户的权限区 ...

  9. 有多个.h引用时,不能有using namespace std

    #include<iostream.h> #include<math.h> //using namespace std; 有多个.h引用时,不能有这个,否则无法运行. void ...

随机推荐

  1. 解决Mac下SourceTree每次都让输入密码的问题

    在Mac上操作sourcetree当pull和push时每次都是让输入密码,非常烦人,虽然大概知道是因为SSH什么的问题,但搜索百度也没发现解决办法. 于是乎搜索谷歌,发现如下解决办法. Source ...

  2. Nginx 高级配置-https 功能

    Nginx 高级配置-https 功能 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.HTTPS工作过程 1>.SSL/TLS SSL(Secure Socket Lay ...

  3. XGBoost 参数介绍

    XGBoost 的设置有三种参数:一般参数,提升参数和学习参数. 一般参数 取决于提升器,通常是树或线性模型提升参数 取决于选择的提升器的相关参数学习参数 取决于指定学习任务和相应的学习目标一般参数 ...

  4. Kth Minimum Clique(2019年牛客多校第二场D题+k小团+bitset)

    目录 题目链接 题意 思路 代码 题目链接 传送门 题意 找第\(k\)小团. 思路 用\(bitset\)来标记每个结点与哪些结点直接有边,然后进行\(bfs\),在判断新加入的点与现在有的点是否都 ...

  5. 大众点评评论数据抓取 反爬虫措施有css文字映射和字体库反爬虫

    大众点评评论数据抓取  反爬虫措施有css文字映射和字体库反爬虫 大众点评的反爬虫手段有那些: 封ip,封账号,字体库反爬虫,css文字映射,图形滑动验证码 这个图片是滑动验证码,访问频率高的话,会出 ...

  6. 201871010118-唐敬博《面向对象程序设计(Java)》第二周学习总结

    博文正文开头格式:(3分) 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.co ...

  7. 浅谈JSON与与JS相关的JSON函数

    本文内容主要引用在微信公众号上看到的一片文章,因为自己对Json了解不是很深入,所以就整理出这篇博文与大家分享! 一. JSON是一种格式,基于文本,优于轻量,用于交换数据 1.一种数据格式 数据的传 ...

  8. 第六章深入python的set和dict

    1.collections中的abc MutableMapping是Mapping的子类 Mapping是Collection的子类 Collection是Sized,Iterable,Contain ...

  9. UID、PID、PPID是什么?

    UID是用户ID,PID是进程ID,PPID是父进程ID. UID UID 用户身份证明(User Identification)的缩写.UID用户在注册后,系统会自动的给你一个UID的数值.意思就是 ...

  10. 抓住九月的尾巴分享一个插件XLSX

    git官网 安装: cnpm install --save xlsx file-saver .vue文件中:1. 引用table插件/自己写table布局 <el-table id=" ...