C++ 命名空间:别再因为命名冲突而烦恼了。
一、前言
实际的软件开发过程中,一个程序往往由多名程序员共同开发。不同程序员在开发过程中都会使用大量的变量和函数,这个时候就会出现变量或函数的命名冲突。虽然每个人的代码都没有问题,但将它们结合到一起就可能会因为命名冲突而出现错误。
在没有命名空间的 C 语言中,如果出现了命名冲突,那只能在所有人写过的代码中,找出那些命名冲突的变量或函数,进行修改。
因为李四经常写出和张三相同的变量名和函数名,没少挨张三的打。公司为了李四的生命安全着想,决定让他们一起学习有命名空间(namespace)的C++
!
二、命名空间
1、命名空间的定义
在C/C++
中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染,它可作为附加信息来区分不同库中相同名称的函数、类、变量等。使用了命名空间即定义了上下文。本质上,命名空间就是定义了一个范围,命名空间中的所有内容都会局限于该命名空间这个范围之中。
定义命名空间,需要使用到namespace
关键字,后面跟命名空间的名字,然后接一对{}
即可,{}
中即为命名空间的成员。
Ⅰ、正常定
这段代码中name1
是该命名空间的名字,它里面可以包含变量、函数、类、typedef
、#define
等,最后用{ }
包围起来。
Ⅱ、嵌套定义
命名空间是可以嵌套定义的,即在一个命名空间中定义另外一个命名空间。
Ⅲ、不连续定义
同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中。在test.h
中有如下定义:
在test.cpp
中有如下定义:
由于两个命名空间的名字相同,所以在编译器严重,这两段可以视为如下代码:
2、命名空间的使用
命名空间的使用有如下三种方式:
加命名空间名称及域解析操作符
使用
using
将命名空间中某个成员引入使用
using namespace
命名空间名称 引入
Ⅰ、域解析操作符
::
是一个新符号,称为域解析操作符,在C++
中用来指明要使用的命名空间。
Ⅱ、using
引入空间成员
使用using
这个新关键字引入空间中的成员。
Ⅲ、using namespace
引入空间所有成员
三、std
命名空间
1、std 的来历
std
是英文单词 S tan dard 的缩写,意思是“标准命名空间”。
它是 C++标准库的命名空间名,C++将标准库的定义实现都放到这个命名空间中。
因为早期的 C++ 还不完善,不支持命名空间,没有自己的编译器,而是将 C++ 代码翻译成 C 代码,再通过 C 编译器完成编译。所以早期标准库将所有功能在全局域中实现,声明在.h 后缀的头文件中,使用时只需包含对应头文件即可,后来又开发了命名空间这一功能,就将类、函数、宏等都统一纳入在std
命名空间下,为了和 C 的头文件区分,也为了正确使用命名空间。
注意:为了避免头文件重名,C++ 库也对头文件的命名做了调整,去掉了后缀.h,所以 C 语言的头文件,在 c++中依旧存在,但在每个名字前还要添加一个 c 字母,并且去掉.h 所以 C 语言的stdio.h
变成了cstdio
,stdlib.h
变成了cstdlib
。比如 C 语言中我们使用printf
函数需要这样写:
而 C++中我们使用printf
函数则需要这样写:
2、std
的使用惯例
在日常练习中,建议直接
using namespace std
即可,这样就很方便。using namespace std
展开,标准库就全部暴露出来了,如果我们定义跟库重名的类型/对象/函数,就存在冲突问题。该问题在日常练习中很少出现,但是项目开发中代码较多、规模大,就很容易出现。所以建议在项目开发中使用,像std::cout
这样使用时指定命名空间 +using std::cout
展开常用的库对象/类型等方式。
四、总结
1、命名空间的三种定义方式
正常定义。
嵌套定义。
不连续定义。
2、命名空间的三种使用方法
域解析操作符
::
。using
关键字部分引入。using namespace
全部引入。
3、 std
使用注意
区分日常使用和项目开发使用。
版权声明: 本文为 InfoQ 作者【子夜的星】的原创文章。
原文链接:【http://xie.infoq.cn/article/6e98f4c49baa65234579dbaa2】。文章转载请联系作者。
评论