目录
为了解决C语言中命名冲突问题,C++引入了命名空间:
rand()函数包含在C语言头文件stdlib.h里,为了解决这个问题,可以这样做:
命名空间里可以放任意的变量、函数、结构体等等
- namespace space2
- {
- int a = 10;
-
- int add(int x, int y)
- {
- return x + y;
- }
-
- struct ListNode
- {
- struct ListNode* next;
- int val;
- };
- //...
- }
命名空间的嵌套
- namespace s3
- {
- int a = 10;
- namespace s4
- {
- int a = 20;
- }
- }
命名空间s3和s4的变量a虽然同名,但并不会冲突!
命名空间的合并
- #include
- namespace s3
- {
- int a = 10;
- }
-
- namespace s3
- {
- int b = 20;
- }
-
- int main()
- {
- std::cout << s3::b << std::endl;
- return 0;
- }
上面的写法相当于:
- namespace s3
- {
- int a = 10;
- int b = 20;
- }
std是C++的标准命名空间,::是作用域限定符,下面会详细介绍。
标准命名空间std是C++标准库中定义的命名空间,用于包含一系列标准库提供的类、函数和对象。它提供了一种组织和封装代码的机制,以避免命名冲突,并将相关的实体进行逻辑上的分组。在程序中使用std命名空间,可以方便地使用标准库中的函数、对象等。
比如C++的标准输入cin输出cout,STL中的vector、sort、queue、stack等等都在std命名空间里。
先来看一个C++输出hello world的程序:
- #include
- using namespace std;//标准命名空间std展开
-
- int main()
- {
- cout << "Hello World" << endl;
- return 0;
- }
其中,iostream文件的包含以及标准命名空间std的展开都是缺一不可的,为什么呢?
头文件和
std
命名空间的关系是,头文件中的内容被包含在std命名空间中。这意味着,如果一个头文件没有使用任何命名空间,那么其定义的所有符号都位于全局作用域;如果一个头文件使用了命名空间std
,那么其定义的所有符号都位于std
命名空间中。在C++标准库中,许多常用的函数、对象和类都被定义在
std
命名空间中,例如std::cout
、std::vector
等。因此,在使用这些函数、对象或类时,需要使用std::
前缀来标识它们属于std
命名空间。
需要注意的是,虽然大部分编译器在实现时并没有严格遵循C++标准,对于原来C语言的头文件,即使按照C++的方式来使用,即#include
这种形式,那么符号可以位于命名空间std
中,也可以位于全局范围中:
如果我们将C++的cstdio头文件换成C语言的stdio.h头文件:
原因是cstdio里的内容都被包含在std命名空间中,而stdio.h里的内容暴露在全局里!
C++将C语言的头文件形式全部由.h结尾改成了以c开头,可能是为了和自己的一套规范相匹配,比如标准C++之前iostream的写法是iostream.h。
不仅仅是头文件里定义的各种变量、函数等,我们自己定义的一系列东西如果暴露在全局里,就很容易造成命名冲突,因此我们在工作中使用C++语言进行工作时最好不要展开命名空间,那么接下来我们将继续介绍命名空间的使用以及作用域限定符。
- namespace s3
- {
- int a = 10;
- namespace s4
- {
- int a = 20;
- }
- int add(int x, int y)
- {
- return x + y;
- }
- }
我拿嵌套命名空间的例子向大家介绍命名空间的使用:
- #include
- namespace s3
- {
- int a = 10;
- namespace s4
- {
- int a = 20;
- }
- int add(int x, int y)
- {
- return x + y;
- }
- }
- int main()
- {
- std::cout << "s3中的add(1,2)=" << s3::add(1,2) << std::endl;
- std::cout << "s3中的a=" << s3::a << std::endl;
- std::cout << "s4中的a=" << s3::s4::a << std::endl;
- return 0;
- }
s4是包含在s3里的,所以要写成s3::s4
如果我们要进行大量的输入输出,一句一句写std::cout岂不是太麻烦了?
为什么最推荐?
①减少代码量
②防止同名变量命名冲突
- #include
- using std::cout;
- using std::endl;
- namespace s3
- {
- int a = 10;
- namespace s4
- {
- int a = 20;
- }
- }
- using s3::a;
- using s3::s4;//err
- using s3::add;
- int main()
- {
- cout << "s3中的add(1,2)=" << add(1,2) << endl;//3
- cout << "s3中的a=" << a << endl;//10
- cout << "s4中的a=" << s3::s4::a << endl;//20
- return 0;
- }
注意,作用域限定符不支持后面跟命名空间:
温馨提醒:平时我们自己写代码可以用,到公司上班了就最好不要写,和别人冲突了就不好了。
- using namespace std;//放在头文件前后都可以
- #include
- //using namespace s3;//放在s3前面就err
- namespace s3
- {
- int a = 10;
- namespace s4
- {
- int a = 20;
- }
- int add(int x, int y)
- {
- return x + y;
- }
- }
- using namespace s3;//ok
- int main()
- {
- cout << "hello world" << endl;
- cout << "s3中的a=" << add(1,2) << endl;
- cout << "s3中的a=" << a << endl;
- cout << "s4中的a=" << s4::a << endl;
- return 0;
- }
使用using namespace+命名空间名称,就相当于少写了一层作用域限定符。
需要注意的是,展开自己的命名空间和展开标准命名空间,自己的必须写在命名空间的定义下面,std的既可以写在头文件上方也可以写在头文件下方。
本文介绍了C++的命名空间,C++的命名空间是为了解决C语言命名冲突的缺陷提出的,对于命名空间的使用,我推荐大家用4.2中的用法,这样有利于培养起优质的代码习惯!
另外,今天是10/24,祝各位程序员节快乐!