1、命名空间的引入
- 命名空间namespace,是C++引入的一种解决全局变量和函数名冲突的机制。C语言没有namespace,但是C++及之后的Java、Python等语言都有。
- namespace的关键点有2个:一是如何解决名称冲突,二是如何合法访问变量。
2、C语言如何解决名称冲突
- 大项目中会有很多C文件,全局变量和函数都是extern链接属性,因此名称冲突是客观存在的。一个项目是一个单体程序,项目中的全局变量和函数理应能互相访问,因此名称冲突是客观存在的。
- C语言中解决名称冲突的办法是:第一,同一个C文件不要太大,由一个人写;第二,每个C文件(或几个C文件构成的一个模块)中所有全局变量和函数前加统一的唯一前缀(例如:usb_init / spi_init);第三,不需要文件外访问的全局变量和函数前面都加static关键字。
- C语言的解决方案可行,C++早期就是这样做的,但这种方法太low,于是引入了命名空间的机制。
3、命名空间如何解决问题
- 为实现命名空间机制,C++引入了namespace关键字,定义格式为namespace xx{ };
- 一个特定名称的namespace的一对大括号内部定义的变量、函数、类等均属于该命名空间内。
- 在命名空间内部互相引用时可以直接使用变量名、函数名等。
- 跨命名空间互相引用时必须同时指定被引用方的命名空间名和变量名/函数名才可以找到
- 命名空间看起来就好像一种前缀
- 命名空间本质上其实是对全局变量和函数在一定范围内链接属性的更改和控制
4、关于语言特性的思考
- 语言特性是语言通过关键字或符号所支持的一种功能特性,入namespace、template、运算符重载、面向对象等。
- 语言特性必定对应解决某种问题,必定在某方面对程序员有帮助。
- 语言特性越多或者设计越复杂,则语言本身就越难使用,但语言就越厉害。
- 语言特性体现为某种语法,本质上靠编译工具链提供支持。
- C++11/14/17/20 的版本变迁,无非是新增或修正某些细节语言特性
- 就事论事讨论编程语言,其实难点都在掌握和熟练运用语言特性上。
5、namespace的定义和使用 定义: namespace xx { void func(void){} };
使用:
- 方式一, xx :: func();
- 方式二, using xx :: func(); func();
- 方式三, using namespace xx; func();
6、C++默认命名空间 默认命名空间又叫全局命名空间,是不用namespace关键字的空间,main函数就处于这个空间。 默认命名空间引用其他命名空间的方法是 xx :: func(); 其他命名空间引用默认命名空间中的方法是 :: func();并且::符号可以省略,直接写成func();也行。
7、C++匿名命名空间 定义: namespace { void func(void){} };
意义:
- 匿名命名空间中的符号是纯文件内部使用的,不需要被外部引用。
- 匿名命名空间效果类似于全局变量和函数加static,但是比C语言中的static使用范围广。
- 匿名命名空间的用法逻辑上符合整个命名空间的一贯原则。
- a文件中无法引用b文件中匿名命名空间中的内容,b文件中匿名命名空间中的内容仅供b文件内部使用。
8、嵌套命名空间 定义: namespace a { namespace b { void func(void){} }; };
使用:
- 外部引用嵌套命名空间内的符号 a :: b :: func();
- 嵌套命名空间内部不太层次间符号的互相引用,可用绝对路径,也可用相对路径。
9、namespace的总结
- 记住最终目标:解决全局名称冲突,同时提供合法互相访问的机制。
- 直接用法(语法),记住如何定义、如何声明、三种使用方法。
- 特殊情况有默认/全局命名空间和匿名命名空间,均为符合一贯原则的特例用法。
- 再次体会“语言特性”的含义。
- C++的语言特性多而复杂,因此学习和使用难度高,关键在于掌握方法,从本质上学。
|