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