【编译器角度】namespace
前言
常用。
1 | using namespace std; |
std就是一个命名空间。
当然最终感觉还是为了便于管理。
1 | namespace hack{ |
把需要用到的函数和变量或者结构体之类的塞到一个命名空间中,这样下次调用起来就很方便:hack::...
正文
1 |
|
这里因为解锁了hack空间,所以里面的变量可以直接调用,但是这样不好的事如果别处有同样定义的变量还是会冲突的。
这也是为什么大部分人其实一开始不会直接using namespace std;
因为std里面有很多的变量啊之类的,就怕你词穷冲突了。解决的办法就是用到啥using一下:using std::cout;
。
良好的代码习惯固然重要,但是后期团队协作还是要看整体风格
全局命名空间
就是说具有链接或者外部属性的对象,只要不存在于定义的命名空间内,就默认定义在全局命名空间中。在全局命名空间中的访问不需要额外指定,除非局部的变量重复了,就需要用到全局命名空间指定。
1 | int a; |
能够看到两个a的值是不同的。
当然这个链接或外部属性是什么意思的,就是全局变量,且非静态的。
像main函数之内的int a;
就是局部的,他就不会存在于全局命名空间。
::前面没东西就是全局
命名空间拓展
在标准头文件中<iostream>
是最常使用的头文件,其中std命名空间自然在其中。
当引用其它头文件,比如<string>
的时候,它也需要从std命名空间中使用。
1 |
|
这说明命名空间是可以拓展的,而且拓展的方法也很简单,在写一个namespace std
的操作即可
1 |
|
可以看到分开写的命名空间hack各自有一个成员,但是调用的时候是统一的。
命名空间的声明
1 | namespace hack{ |
对于变量,这种情况我们默认就当成定义了,因为即便没有初始化也有可能分配到一个垃圾值。或者被优化掉。
声明一个变量之前提到过加上extern
1 | namespace hack{ |
1 |
|
这样的value还是处于全局命名空间。
1 | //main.cpp |
1 | //main.h |
照例输出一下:
并且函数也是同样的
1 |
|
1 |
|
输出一下:
所以声明和定义选择上跟源文件和头文件、源文件和源文件之间的联系是一样的
命名空间的嵌套
函数能套娃,命名空间也能套娃
1 | namespace hack{ |
多套几层也没啥事,反正能够通过::
访问到。
未命名的命名空间
1 | namespace { |
未命名的命名空间中的声明一律为内部连接属性,包括用extern声明的内容,且未命名的命名空间只在本转换单元有效。
一个函数不能同时出现在多个源文件当中,因为在编译的时候会发生重复定义。
按照C语言当时的习惯就是使用static或者inline之类的,当然c++之后是不期望这么用的。
1 | namespace{ |
1 | void hhh(){ |
这种情况下,hhh函数不会发生报错,因为它存在于未命名命名空间中,具有内部连接属性,跟外部不冲突。
而且即使不同源文件都出现:
1 | namespace{ |
也不会像之前的命名空间会自然拓展,未命名命名空间是完全独立的。
命名空间别名
之前给结构体哪些创建别名都是通过typedef
命名空间有自己起别名的方式namespace a = xxx::xxx
之类的
1 | namespace hack{ |
那么下次调用hackbar的参数,就可以直接从a::hack_he
了。
结语
c++特性,还是要好好了解的,毕竟后面还有类。