C++
的命名空间
命名空间是什么
先举个例子,为什么要命名空间
#include <iostream>
using namespace std;
int a = 10; //全局变量
void test() {
int a = 20; //局部变量
cout <<"a:" << a << endl;
}
int main()
{
cout << "Hello World!\n";
test();
return 0;
}
程序员在编程中很容易出现上面的情况,全局变量和局部变量名称冲突。使用不同的变量名固然是一种好的方法,但是在大型项目中,我们很难避免使用相同的变量名,尤其是这个变量名有着很好的实际意义,对代码可读性起到作用时,修改变量名就显得没那么明智了。C++
为我们提供了一种机制,即命名空间,这可以理解成通过给不同的变量和方法分类的手段起到避免命名冲突的机制,不同的命名空间可以被当作不同的类。
创建命名空间
namespace A{
int a = 10;
}
namespace B{
int a = 20;
}
void test(){
cout << "A::a : " << A::a << endl;
cout << "B::a : " << B::a << endl;
}
在第一部分中我们举的例子里,如果我想访问库变量可以通过下方这种方式完成
//全局变量
int a = 10;
void test(){
int a = 20;
cout << "局部变量a:" << a << endl;
cout << "全局变量a:" << ::a << endl;
}
注意命名空间只能在全局范围内定义,比如下面这种情况是不被允许的。
void func(){
namespace A{
int a = 10;
}
namespace B{
int a = 20;
}
}
命名空间允许嵌套
namespace A{
int a = 10;
namespace B{
int a = 20;
}
}
除此之外,namespace还要以下的特性:
- 命名空间是开放的,即可以随时把新的成员加入已有的命名空间中
namespace A{
int a = 10;
}
namespace A{
void func(){
cout << "hello namespace!" << endl;
}
}
- 声明和实现可分离
#pragma once
namespace MySpace{
void func1();
}
void MySpace::func1(){
cout << "MySpace::func1" << endl;
}
- 没有名字的命名空间,意味着命名空间中的标识符只能在本文件内访问,相当于给这个标识符加上了static,使得其可以作为内部连接)
namespace{
int a = 10;
void func(){ cout << "hello namespace" << endl; }
}
void test(){
cout << "a : " << a << endl;
func();
}
- 命名空间别名
namespace veryLongName{
int a = 10;
}
void test(){
namespace nick_name = veryLongName;
cout << "veryLongName::a : " << nick_name::a << endl;
}
using 声明和using 编译指令
// using声明
using A::paramA;
using A::funcA;
using namespace A;
cout << paramA << endl;
cout << paramB << endl;
- using声明使名称空间中的特定标识符可用,比如第一个
- using 编译指令使得名称空间里得所有标识符可用。例如第二个,使得A空间里的所有名称可用,且不用再次声明其命名空间
命名空间的使用
当引入一个全局的using编译指令时,就为该文件打开了该命名空间,它不会影响任何其他的文件,所以可以在每一个实现文件中调整对命名空间的控制。当发现某一个实现文件中有太多的using指令而产生命名冲突时,就要对该文件做个简单的改变,通过明确的限定或者using声明来消除名字冲突,这样不需要修改其他的实现文件。