命名空间:c++中在c语言基础上新增的一个用于解决开发中函数以及变量等命名冲突的方案
(1)命名空间格式
(2)域解析操作符
(3)using指令
(4)命名空间嵌套
(5)不连续的命名空间
(6)匿名命名空间
例如我们一条村中有两个人的名字一样都叫xyq;当他们两个呆在一起的时候,如果你想叫他们其中一个去玩的话,直接叫xyq,他们就会不知道你叫的是他们之间的哪一个,这个时候我们为了能够区分我们现在需要叫去玩的是哪一个,于是就会在他们的名字前面加上他们的父母名字或者一些能够区分他们身份的信息
因为在开发中不是所有代码都是我们自己一个人全部写完的,例如:
#include <iostream>
int a = 10;
int a = 20;//此时编译时会直接报错,提示重复定义
int main()
{}
所以我们不可避免地会遇到命名冲突的情况于是c++中便设计了命名空间这个概念,实际上就是指定了一个范围(相当于加上命名空间的名称来区分变量的命名空间作用域)
(1)命名空间格式:
namespace 命名空间名称
{
//成员:变量,函数,类,结构体
}
(2)域解析操作符
在调用命名空间内的成员时我们需要加上域解析操作符 ::,用于指明该变量属于哪一个命名空间内的变量
#include <iostream>
namespace AA
{
int a = 10;
}
int main()
{
AA::a = 10;
}
于是我们上面提示重复定义的代码可以改成以下格式:
#include <iostream>
namespace AA
{
int a = 10;
}
namespace BB
{
int a = 20;
}
int main()
{
AA::a = 10;
BB::a = 20;
}
此时代码再去编译就不会产生错误了,因为两个变量已经被放到AA和BB的两个不同范围命名空间内了,不在同一范围内所以不会报错
(3)using指令
using指令是C++中为了方便我们在频繁使用一个命名空间内的变量了,无需一直频繁地在变量前加命名空间名(注:个人不太建议自己编写地命名空间使用using指令),当我们使用using指令后就要注意变量命名是否会产生冲突了,因为函数内使用了同名变量,在调用时若没写命名空间名称则会优先调用函数内定义的变量,此时我们就不行直接写变量名去调用命名空间内的变量了,就需要在调用我们命名空间内的变量前加上命名空间名称;例如:
#include <iostream>
namespace AA
{
int a = 10;
}
using namespace AA; //这个代表可以不加命名空间名称访问AA里的所有变量或者函数
//using namespace AA::a //代表我们可以不加命名空间名称访问AA里的a
int main()
{
a = 10;
int a = 9; //此时的a在没写命名空间名时会被优先调用(作用域问题)
std::cout << "a =" << a << std::endl;//a=9
std::cout << "AA::a =" << AA::a << std::endl;//AA::a=10
}
运行结果:
(4)命名空间嵌套
命名空间嵌套:即一个命名空间里还包含了一个或多个其他的命名空间,且支持多层命名空间嵌套;当我们一个命名空间中有多个命名空间时,我们在调用时需要逐层地进去,直到我们需要使用地变量所在地命名空间,例如:
#include <iostream>
namespace AA
{
int a = 10;
namespace BB
{
int a = 20;
}
}
int main()
{
AA::a = 10;
AA::BB::a = 20;
std::cout << "AA::a =" << a << std::endl;//
std::cout << "AA::BB::a =" << AA::BB::a << std::endl;//
}
运行结果:
因为我们想调用BB这个命名空间中地a时,因为BB它在AA地命名空间内,所以我们要先指明BB在AA这个命名空间内,再进一步去告诉编译器我们需要调用地a在BB这个命名空间内
(5)不连续的命名空间
不连续的命名空间,即我们可以在多处对同名的命名空间进行创建,但是此时新创建的同名命名空间会被当成是第一个命名空间的补充
测试代码:
#include <iostream>
namespace AA
{
int a = 10;
}
namespace AA
{
//int a = 20; //此时会报错,因为同一个命名空间不允许两个同名变量
int b =30;
}
int main()
{
std::cout << "AA::a =" << AA::a << std::endl;
std::cout << "AA::b =" << AA::b << std::endl;
}
运行结果:
(6)匿名命名空间(unnamed namespace)
匿名命名空间即没有名称的命名空间,用于定义只能在本编译单元tu(translation unit)中使用的变量或函数等,当我们使用匿名空间时编译器在内部会自动为我们生成一个唯一的名字 _UNIQUE_NAME,且会自动帮我们调用using指令 ,且在我们调用匿名命名空间内的成员时需要加上域解析操作符::;即:
//匿名空间
namespace
{
int a = 10;
}
/*-----------------分界线------------------------*/
//等价于
namespace __UNIQUE_NAME_
{
int a = 10;
}
using namespace __UNIQUE_NAME_;
//匿名命名空间成员调用
int main()
{
::a = 20;//匿名命名空间成员前加域解析操作符::
}
我们使用了匿名命名空间时同时也有一个全局变量与匿名命名空间内的某一变量名冲突时,编译器会默认把该该全局变量当成匿名命名空间内的成员,当我们对全局变量进行操作时,相当于是在操作匿名空间内的成员变量 ,例如:
#include <iostream>
namespace AA
{
int a = 10;
}
using namespace AA;
//当全局变量与匿名空间存在同名函数时,编译器会默认把它们当成是同一个匿名空间内的变量
namespace {
int a = 20;
}
int a=30;
int main()
{
//std::cout << a <<std::endl; //直接打印a会报错
std::cout << "AA::a =" << AA::a << std::endl;//
std::cout << "a =" << ::a << std::endl;//此时调用a为匿名空间成员
}
运行结果: