详解c++的命名空间namespace
1、命名空间的概述
在c++中,名称(name)可以是符号常量、变量、函数、结构、枚举、类和对象等等。
工程越大,名称互相冲突性的可能性越大。另外使用多个厂商的类库时,也可能导致名称冲突。为了避免,在大规模程序的设计中,以及在程序员使用各种各样的C++库时,这些标识符的命名发生冲突,标准C++引入关键字namespace(命名空间/名字空间/名称空间),可以更好地控制标识符的作用域。
2、命名空间的定义
//定义一个名字为A的命名空间(变量、函数)
namespaceA{inta=100;}namespaceB{inta=200;}voidtest02(){//A::a a是属于A中
cout<<"A中a = "<<A::a<<endl;//100
cout<<"B中a = "<<B::a<<endl;//200
}
3、命名空间只能全局范围内定义(以下为错误写法)
4、命名空间可以嵌套
namespaceA{inta=1000;namespaceB{inta=2000;}}voidtest03(){cout<<"A中的a = "<<A::a<<endl;//1000
cout<<"B中的a = "<<A::B::a<<endl;//2000
}
5、命名空间是开放的,即可以随时把新的成员加入已有的命名空间中(常用)
namespaceA{inta=100;intb=200;}//将c添加到已有的命名空间A中
namespaceA{intc=300;}voidtest04(){cout<<"A中a = "<<A::a<<endl;//100
cout<<"A中c = "<<A::c<<endl;//200
}
7、命名空间中的函数 可以在“命名空间”外 定义
namespaceA{inta=100;//变量
voidfunc();}voidA::func()//成员函数 在外部定义的时候 记得加作用域
{//访问命名空间的数据不用加作用域
cout<<"func遍历a = "<<a<<endl;}voidfunb()//普通函数
{cout<<"funb遍历a = "<<A::a<<endl;}voidtest06(){A::func();funb();}
8、无名命名空间,意味着命名空间中的标识符只能在本文件内访问,相当于给这个标识符加上了static,使得其可以作为内部连接(了解)
namespace{inta=10;voidfunc(){cout<<"hello namespace"<<endl;}}voidtest(){//只能在当前源文件直接访问a 或 func
cout<<"a = "<<a<<endl;func();}
9、给命名空间 取个别名(了解)
namespaceveryLongName{inta=10;voidfunc(){cout<<"hello namespace"<<endl;}}voidtest(){namespaceshortName=veryLongName;cout<<"veryLongName::a : "<<shortName::a<<endl;veryLongName::func();shortName::func();}
https://zhuanlan.zhihu.com/p/126481010
==========================
命名空间
《维基百科》中说 “命名空间是对作用域的一种特殊的抽象”,在这里我用一个比方来具体说明一下:
比如张三在公司 A,他的工号是 111,李四在公司 B,他的工号也是 111,因为两个人在不同的公司,他们俩的工号可以相同但是不会引起混乱,这里的公司就表示一个独立的命名空间,如果两个人在一个公司的话,他们的工号就不能相同,否则光看工号也不知道到底是谁。
其实上面举的这个例子的特点就是我们使用命名空间的理由,在大型的计算机程序中,往往会出现成百上千的标识符,命名空间提供隐藏区域标识符的机制。通过将逻辑上相关的标识符构成响应的命名空间,可以使整个系统更加的模块化。
我在开头引用的《维基百科》的那句话说 “命名空间是对作用域的一种特殊的抽象”,它其实包含了处于该作用域内的标识符,且它本身也用一个标识符来表示。在 Python 中,命名空间本身的标识符也属于更外层的一个命名空间,所以命名空间也是可以嵌套的,它们共同生活在 “全局命名空间” 下。
简言之,不同的命名空间可以同时存在,但是彼此独立,互不干扰。当然了,命名空间因为其对象的不同也有所区别,可以分为以下几种:
1.本地命名空间:模块中有函数或者类的时候,每个函数或者类所定义的命名空间即是本地命名空间,当函数返回结果或者抛出异常的时候,本地命名空间也就结束了。
2.全局命名空间:每个模块创建了自己所拥有的全局命名空间,不同模块的全局命名空间彼此独立,不同模块中相同名称的命名空间也会因为模块的不同而不相互干扰。
3.内置命名空间:当 Python 运行起来的时候,它们就存在了,内置函数的命名空间都属于内置命名空间,所以我们可以在任何程序中直接运行它们。
程序查询命名空间的时候也有一套顺序,依次按照本地命名空间 ,全局命名空间,内置命名空间。
deffun(like):
name ='rocky'
print(locals())
fun('python')
访问本地命名空间使用 locals 完成,我们来看一下结果:
{'name':'rocky','like':'python'}
从上面的结果中可以看出,命名空间中的数据存储的结构和字典是一样的。可能你已经猜到了,当我们要访问全局命名空间的时候,可以使用 globals。
关于命名空间还有一个生命周期的问题,就是一个命名空间什么时候出现,什么时候消失,这个很好理解,就是哪部分被读入内存,哪部分的命名空间就存在了,比如我们在上面说的,Python 启动,内置命名空间就建立。
谈谈你对命名空间的理解
1)namespace命名空间的存在是为了实现在同一个工程中,通过使用命名空间可以实现,同一变量名的多次定义而不报错。
2)可以使得代码模块化。将逻辑相关的标识符组织起来,系统更加整洁、清楚;
3)随着工程量的增加,变量命名上避免不了出现重名,主要原因是:为了防止名称冲突(在不同的命名空间中,即使有两个相同的变量名,也是两个不同的变量),在实际工作中,我们基本都使用标准命名空间。
4)命名空间只能在全局范围内进行定义,不可以定义在函数内部。
5)在命名空间内,可以用于存放变量,函数,结构体,类,同时也可以嵌套其他的命名空间。
6)存在匿名的命名空间,类似静态全局变量,就是为了防止让其他工程通过外部调用,使用此匿名空间。
namespace
{
int data = 123;
}
可以在本文件中 直接使用 data,限制这个匿名命名空间中的成员只能在本文件中使用,类似C语言中的static修饰的全局变量。
7)命名空间是可以起别名的。因为命名空间允许嵌套,所以可能出现一些比较长的名字。
namespace A
{
namespace B
{
namespace C
{
double pi=3.141592653;
}
}
}
//方式一:
A::B::C::pi
//方式二:
namespace ABC=A::B::C;
cout<<ABC::pi;//是不是简洁很多
8) ----引进整个命名空间 ---将这个盒子 全部打开
例如:using namespace 命名空间的名字;
---引进命名空间的某个成员 --》将这个盒子中某个成员的位置打开
例如:using 命名空间的名字::成员名;
---调用的时候指定是哪一个命名空间下的成员(建议使用这种方式)
例如:命名空间的名字::成员名
比如
---cout<<space1::val;
---space1::print();
9)同名命名空间 :命名空间可以分开定义 ,也就是说,你在定义一个命名空间之后,如果后面想要在这个命名空间里面再次添加某些数据 成员或者函数成员,可以再次接着定义。
————————————————
版权声明:本文为CSDN博主「大杨在线」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_59996036/article/details/121643067