经实验验证,修正对using namespace std的认识
备注①: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的认识的更多相关文章
- using namespace std 和 using std::cin
相较using std::cin使用using namespace std不会使得程序的效率变低,或者稳定性降低,只是这样作会将很多的名字引入程序,使得程序员使用的名字集合变小,容易引起命名冲突. 在 ...
- namespace std
c++中使用namespace来防止命名冲突(重命名),我们经常使用的一些函数和变量都被放在一个叫std的namespace中,如标准I/O流操作,vector等等.我们在每一个文件中都可使用std中 ...
- C++ using namespace std(转载)
转载自http://www.kuqin.com/language/20080107/3532.html 感谢这位大神的解答! 以下的内容摘抄自转载的文章里面的部分内容. 早些的实现将标准库功能定义在全 ...
- 不要在头文件中使用 using namespace std;
不要在头文件中使用(using namespace std;). 若你使用了using namespace std;,在某一头文件中,那么包含这些头文件的文件就失去了"namespace ...
- using namespace std
using namespace std std 是一个命名空间..不同的命名空间可以有相同的类名被定义 ..using namespace std;就是指明下面的程序使用std,如果不用这句指明的话就 ...
- #include<iostream.h>与#include<iostream> using namespace std的区别
所谓namespace,是指标识符的各种可见范围.C++标准程序库中的所有标识符都被定义于一个名为std的namespace中. 一 :<iostream>和<iostream.h ...
- 关于using namespace std
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~关于using namespace std ~~~~~~~~~~~~~~~~~~~~~~~~~~~ ...
- 实验验证sys和system用户全库导出的区别
我们在做逻辑数据泵全库导出的时候,有两种流行的写法,一种是sys用户导出,一种是使用system用户导出. 现在想知道二者之间有什么区别?实验验证之前不妨先思考一下: sys和system用户的权限区 ...
- 有多个.h引用时,不能有using namespace std
#include<iostream.h> #include<math.h> //using namespace std; 有多个.h引用时,不能有这个,否则无法运行. void ...
随机推荐
- mysql数据库之主从复制+双主--MMM
mysql复制:在主数据库中,前端用户每执行一个写操作/语句,都会在二进制日志中保存一个事件,把这个事件从mysql的服务器中3306端口发送给从服务器,从服务器把这个事件接受下来,接受下来先保存在本 ...
- java lambda表达式检查list集合是否存在某个值
import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; public class ...
- 《Pro Continuous Delivery With Jenkins 2.0》随书笔记
今天同时看完<Pro Continuous Delivery With Jenkins 2.0>, 这书与工作关系很大,但也是快速翻翻. 本书着重点jenkins高可用环境搭建,与gith ...
- python操作mysql(增、删、改、查)
用python操作数据库,特别是做性能测试造存量数据时特别简单方便,比存储过程方便多了. 连接数据库 前提:安装mysql.python,参考:https://www.cnblogs.com/Uncl ...
- 【oracle】drop,truncate,delete用法
drop: drop table 表名:删表 truncate: truncate table 表名:清空数据 delete: delete table 表名 [where 条件]:删某数据 日志:d ...
- 【Linux】查看端口和进程
netstat -tunlp ps -ef|grep process_name
- RabbitMQ六种队列模式-工作队列模式
前言 RabbitMQ六种队列模式-简单队列RabbitMQ六种队列模式-工作队列 [本文]RabbitMQ六种队列模式-发布订阅RabbitMQ六种队列模式-路由模式RabbitMQ六种队列模式-主 ...
- 第05组 Beta冲刺(1/4)
第05组 Beta冲刺(1/4) 队名:天码行空 组长博客连接 作业博客连接 团队燃尽图(共享): GitHub当日代码/文档签入记录展示(共享): 组员情况: 组员1:卢欢(组长) 过去两天完成了哪 ...
- 前端/H5/JS:通过URL下载文件并转存到其他服务器(微信),Blob文件转File文件
现在有一个图片URL,在自己服务器上,一个微信提供的媒体文件上传URL,我在前端通过JS实现转存微信服务器 1. http://file.xxx.com/asd.jpg 自己的 2.https://a ...
- 5-STM32物联网开发WIFI(ESP8266)+GPRS(Air202)系统方案安全篇(配置MQTT的SSL证书,验证安全通信)
4-STM32物联网开发WIFI(ESP8266)+GPRS(Air202)系统方案安全篇(为域名申请SSl证书) 前面的准备工作终于完了 复制这两个证书 放到云端MQTT的这个位置,其实放哪里都可以 ...