您现在的位置是:首页 >技术交流 >【C++】命名空间网站首页技术交流
【C++】命名空间
1. 由来
命名空间时怎么来的?它又是什么,让我们一起来看一下吧
首先了解:在同一个域中不能同时出现重名的变量或函数名等(不同域中可以尽管是全局与局部域)
ok 我们来看
在工程项目里,一开始用 C语言 开发时,可能你在你的项目文件中给你的变量(或函数)取了一个好名字(ergou(bushi) maxSize ),用了一段时间,并且在你的项目文件中出现了一千多次,平常觉得没什么嗯很不错好名字……但是在和其他人的项目文件合并的时候(因为是一个项目要合并到一起),一合并发现 —— !!??嗯? maxSize重定义,然后发现错误:原来和你一起做项目的佳乐在写它的项目文件的时候,也定义了一个 maxSize ,隔壁的天天不洗澡的佳乐居然也用了这个名字,这不行,我得和它一决雌雄,让它改成另一个名字(因为一个域内不能出现重名的现象)(骂骂咧咧:什么档次,和我用一样的等离子变量名)
如果这样的话,我和佳乐之间就一定得有一个人去把那上千个重复的变量名改成另一个名字(假设佳乐也用在了一千个地方)
——— 这时祖师爷走过来说,别吵吵
或者在包了一个库之后发现库里也有一个变量名也叫 maxSize 那样只能改个名字,虽然已经用了上千次,但是还是得改
其实真正的,祖师爷也受不了 C语言 这种现象,所以在C嘎嘎中定义了一个定西 —— 命名空间
2. 怎么用
2.1 格式
|
如上的格式,namespace 是关键字,其后定义命名空间的名字(每个命名空间我们可以给它起名字,当然,最好不要取名为 ergou),后面即是大括号,大括号后面没有冒号;大括号里面可以定
义变量,函数名,结构体等都可以在命名空间里定义
而命名空间怎么做到避免重名的作用呢
2.2 原理及其使用
想要知道怎么避免重名,得先了解代码运行的编译阶段,符号(变量名,函数,结构体等)汇总
分析等的顺序(找变量名的顺序)
害(念第四声)得知道几个域的大致范围:
而符号汇总的时候,是先在局部域中进行汇总,再是全局域,关键来了:命名空间没有展开,我们的 visual stdio 不会进入命名空间的,只有你通过特定的代码展开了对应的领域,编译器才会在
搜索完 局部域 全局域之后,进入特定的命名空间域
一步一步来,先总结一下运行的编译时(符号汇总等)搜索的顺序:
局部域 → 全局域 → 展开了的命名空间域 (没展开的命名空间域进不去)
验证一下:
就比如上面的标了域的图中的代码,要打印 a,流程如下:
说法1:(这里面对 a)开始编译代码,进行符号汇总,先收集局部域的符号,找到一个 a;再去全局域中收集符号,找到另一个 a(不同域中可以定义同名的变量so不报错),没有展开命名空间域,所以
不进 zhuandrong 这个命名空间中收集符号
printf 打印 a 打印到的是局部变量的 a。有人会说不是全局还有一个 a 吗,为什么不打印那个 a。这个就涉及刘德华问题了(当局部和全局中两个变量同名,就近原则先访问更近的那一个,全局的
相当于被屏蔽了)
说法2:先在局部域中进行查找,在该局部域中找到一个a后停止查找a,不会再去全局域中进行查找
思考一下那种说法是对的
那可以把 变量,函数名,结构体等 放进命名空间之后,怎么拿出来用呢,用 " :: "
有三种方法:
注:这里是以全局域中的命名空间为锚点,命名空间和全局域中是亲和的单层关系(没有嵌套)
1、展开部分(本质:在全局域中展开)(首选)
using 空间名 :: a;
etc. using zhuandrong :: a;
(记得加分号)
这样的操作相当于什么呢,在内存的角度大概干了什么呢?
using zhuandrong::a; 这步操作相当于把 命名空间zhuandrong 中的变量 a 暴露到全局域,这样的话在进行编译(符号汇总等)的时候,有了 using zhuandrong::a; 这条语句,编译的时候会把命名空间里的对应要展开的内容展开到当前域(这里是全局域中(只是展开不是完全放入)),这样在
程序执行的时候,就可以在全局域找到展开的目标变量或函数
那原本全局域中有一个 a,命名空间中也有 a 被我展开了,会不会冲突呢?
如果真正理解了刚刚展开的过程,不问就已心知肚明了
正因为这样展开部分是展开到全局域,所以当全局域中原本有一个变量名与展开的变量名重名,自然会报错,同一个域不能有重名变量或函数等,而展开的部分是真正的加载到全局域(正确的
是展开到其父级域中),而同级域中不能有重名,so
2、语句中调用 (本质:局部域中展开)
printf( "%d ", zhuandrong::a );
这种方法是直接在语句中调用,但是这里不推荐只使用这一种方法,如果只用这一种,那有大量
语句都要此命名空间中的变量呢,一个一个加,太矬了
但是这个方法与第一种方法联合起来一起用效果会很好----- 命名空间中,要大量使用的内容进行全
局域展开,只用一两下可以在局部域中展开就哦
3、领域展开(极不推荐全部展开到全局域)
using namespace zhuandrong;
这样相当于把 zhuandrong 这个命名空间的全部内容放到了它所在的父级域
但是极不推荐直接展开到全局域,因为命名空间就是为了和当前域级隔离(避免重名)创建出
来,现在如果全部展开,那不就返祖了嘛,本质是更危险了,可能会出现重名
(当然日常练习也可以使用,但是不要忘记本质)
3. 理解
总觉得没有找到好的比喻来作比喻,所以现阶段只是初级理解
初级理解:可以把命名空间理解成一个锦囊,一个背包(或者围起来的封闭的围墙,栅栏),这个背包的作用是起到一个隔离的作用,如果你是科技迷,那就太好了:而变量不能重名可以理解为平行宇宙的正反粒子,只要互相一接触,就会同时湮灭(现在的你和平行宇宙中的你一接触,
会同时湮灭消失);而我们的栅栏正好可以把你和平行宇宙中的那个你隔开来,扯远了
应该是锦囊,两个相同的物品(正反粒子)不能同时出现在同一个空间,而我们的锦囊(命名空间)就可以做到隔离当前空间的作用,这样把两个会冲突的物体分隔到了不同的空间,自然不会
起冲突
更多的还是要理解在具体中的用法,在实际当中的意义,处境(俗称 “会意”)
主要解决全局域的重名冲突问题