命名空间的理解

详解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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值