C++的命名空间namespace详解及特殊情况分析

news2024/10/1 19:33:00

这里写目录标题

  • 历史来源
  • 意义
  • 定义
  • 使用
  • using namespace std弊端

历史来源

最开始的C++ 头文件仍然以.h为后缀,它们所包含的类、函数、宏等都是全局范围的。后来 C++ 引入了命名空间,计划重新编写库将类、函数、宏等都统一纳入一个命名空间std
但改版后的c++库致使旧c++库无法使用,在当时产生了巨大的反响,于是,C++ 开发人员想了一个好办法,保留原来的库和头文件,它们在 C++ 中可以继续使用,然后再把原来的库复制一份,把类、函数、宏等纳入命名空间 std 下,就成了新版 C++ 标准库。这样共存在了两份功能相似的库,使用了老式 C++ 的程序可以继续使用原来的库,新开发的可以使用新版的 C++ 库。
为了避免头文件重名,新版 C++ 库也对头文件的命名做了调整,去掉了后缀.h而对于原来C语言的头文件,也采用同样的方法,但在每个名字前还要添加一个c字母,stdio.h变成了cstdio,stdlib.h变成了cstdlib

意义

提到命名空间就不得不提到C语言了,由于C++是C语言的扩展,所以C++的开发人员就注意到C语言中命名冲突,例如一个团队的多个人员参与了一个文件管理系统的开发,他们都定义了一个全局变量 a,用来指明当前打开的文件,将他们的代码整合在一起编译时,很明显编译器会提示 重复定义(Redefinition)错误。

有一个常用的经典案例

#include<stdio.h>
#include<stdlib.h>
int rand = 0;//全局变量
int main()
{
	printf("%d\n", rand);
	return 0;
}       
// 出现了编译错误,error C2365: “rand”: 重定义;以前的定义是“函数”
//因为rand是一个C语言标注库中的函数,在编译时发现你使用的库中函数一样的名字就报错了

这个案例我们会在文章末尾进行再度分析

结论😗: 没有命名空间的话,在C/C++中,标识符(变量、函数和类)都是大量存在的,并且都存在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染.

定义

为了解决合作开发时的命名冲突问题,C++ 引入了命名空间Namespace的概念。
当你要定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接一对{ }即可,{ }中即为命名空间的成员

①普通定义:

//项目中成员分别以自己的名字定义了命名空间
namespace zs//张三的变量定义
{  
    int a = 1;
}
namespace ls //李四的变量定义
{  
    int a = 2;
}

②嵌套定义


namespace demo1
{
	int a = 0;
	int Add(int left, int right)
	{
		return left + right;
	}
	namespace demo2
	{
		int b = 0;
	}
}

③不同文件同名命名空间合并

// test.cpp
namespace N1
{
	int a;
	int b;
	int Add(int left, int right)
	{
		return left + right;
	}
}

// test.h
namespace N1
{
	int Mul(int left, int right)
	{
		return left * right;
	}
}
//test.cpp 和 test.h中的 N1 最终会合并为一个

使用

正因为有了命名空间,所以使用对于的变量函数等,就要指明是具体哪个命名空间
在C++ 中 using 用于声明命名空间至全局命名空间(说白了就是解开std的束缚,让命名空间std完全暴露出来),使用命名空间也可以防止命名冲突。
:: 是一个新符号,称为域解析操作符,在C++中用来指明要使用的命名空间

1.命名空间名称+域解析操作符

//对应上面第一个普通定义的例子
zs::a = 10;
ls::a = 20;

2.using + 命名空间 :: 一个成员

using zs::a; //它的意思是,using 声明以后的程序中如果出现了未指明命名空间的 a
			 //就使用 zs::a;但是若要使用ls定义的 a,仍然需要 ls::a。

a = 10; //此时的a时zs命名空间
ls::a = 20;//ls命名空间

3.using namespace +命名空间

using namespace zs; //在 using 声明后,如果有未具体指定命名空间变量产生了命名冲突
			        //那么默认采用命名空间 zs 中的变量。
a = 10; //此时的a时zs命名空间
ls::a = 20;//ls命名空间

对于上面的那个经典案例,我们就可以用到命名空间的知识进行解决

#include<iostream>
namespace hk
{
	int rand = 0;
};
int main()
{
	printf("%d", hk::rand); //用到第一种方法进行解决
	return 0; 
}

但是如果你使用第二种,第三种方法,就会出错
在这里插入图片描述
在这里插入图片描述

接下来我们就着重对这个例子进行分析
首先可能会有人有疑惑为什么 头文件是< iostream > ,并没有< cstdio >为什么也会找到< cstdio >里面的rand()函数

那是因为头文件的引用时进行了层层包含
iostraeam 里面引用了
#include < istream >
istream
引用了
#include < ostream >
引用了
#include < ios >
引用了
#include < xlocnum >
引用了
#include < cstdlib >
里面有如下定义
在这里插入图片描述

并且按照 C++ 的方式来使用C语言的头文件,即#include < cstdio >这种形式,那么符号可以位于命名空间 std 中,也可以位于全局范围中.
①.使用命名空间std

#include <cstdio>
int main()
{
    std::printf("kklovecode");
    return 0;
}

②.不使用命名空间 std

#include <cstdio>
int main()
{
    printf("kklovecode");
    return 0;
}   //在大部分编译器中都能通过

由此说明大部分编译器在实现时并没有严格遵循C++标准,它们对两种写法都支持,程序员可以使用 std 也可以不使用。
①写法是标准的,②不标准,虽然它们在目前的编译器中都没有错误,依然推荐使用①写法,因为标准写法会一直被编译器支持,非标准写法可能会在以后的不再支持。

所以由此可见,在使用C++的模式下使用C语言库里面的,编译器并没有严格按照C++的规范,所以就出现了上面经典案例中用第二种和第三种方法时,即使你根本没有手动使用using去声明这个命名空间(即命名空间暴露出来),但是仍然能够使用std里面的rand()函数.

using namespace std弊端

相信大家在看许多C++资料时,都会发现很多都是直接在头文件下面写上 using namespace std;用的就是第三种方法使用std命名空间
如:

#include<iostraeam>
using namespace std;
int main()
{
  ...
}

因为标准库可能会升级,这样升级编译使用的C++版本的时候有可能因为引入了新的符号跟自己代码里的命名冲突,这样做增加了命名冲突的风险.
并且C++设置std命名空间就是不想你直接使用,而当你直接用using namespace std; 将其暴露出来,也多少有点违背C++本意.
总结😗:但一般来说,升级C++版本最多几年也就做一次,冲突的可能性也并不大,所以很多教材中的代码像那样使用节约时间成本也并非没有道理,但在中大型项目开发中是不被推荐的,适合使用第二种或者第三种方式

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/983568.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

springboot 下 activiti 7会签配置与实现

流程图配置 会签实现须在 userTask 节点下的 multi instance 中配置 collection 及 completion condition; collection 会签人员列表&#xff1b;element variable 当前会签变量名称&#xff0c;类似循环中的 item;completion condition: 完成条件。 ${taskExecutionServiceIm…

Credo推出业界首款单片集成CMOS VCSEL驱动器的800G光DSP芯片

针对AOC及短距&#xff08;SR&#xff09;光模块优化的新型Credo DSP&#xff0c;适用于下一代超大规模数据中心/AI应用 加州圣何塞和中国深圳&#xff0c;2023年9月6日——Credo Technology&#xff08;纳斯达克股票代码&#xff1a;CRDO&#xff09;今日发布两款新品&#x…

EasyPhoto:基于 SD WebUI 的艺术照生成插件来啦!

作者 &#xff1a;wuziheng 背景介绍 最近&#xff0c;基于生成式AI技术批量产出真/像/美的个人写真应用非常受欢迎。同时&#xff0c;随着 Stable Diffusion 领域开源社区的快速发展&#xff0c;社区也涌现了类似 FaceChain 的开源项目&#xff0c;帮助开发者开发个性化的真…

14 合并区间

合并区间 题解1 左端点排序后合并&#xff08;可证连续&#xff0c;贪心&#xff09;题解2 双指针&#xff08;优化&#xff09; 以数组 i n t e r v a l s intervals intervals 表示若干个区间的集合&#xff0c;其中单个区间为 i n t e r v a l s [ i ] [ s t a r t i , e n…

计算机视觉-OpenCV入门讲解

&#x1f389;作者简介&#xff1a;在读计算机研究生&#xff0c;目前研二。主要研究方向是人工智能和群智能算法方向。目前熟悉python网页爬虫、机器学习、计算机视觉&#xff08;OpenCV&#xff09;、群智能算法目前正在学习深度学习的相关内容。 &#x1f4c3;个人主页&…

jar包或exe程序设置为windows服务

最近在使用java和python制作客户端时突发奇想&#xff0c;是否能够通过一种方法来讲jar包和exe程序打包成windows服务呢&#xff1f;简单了解了一下是可以的。 首先要用到的是winSW&#xff0c;制作windows服务的过程非常简单&#xff0c;仅需几步制作完成&#xff0c;也不需要…

2023 Google 开发者大会

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

C++(Liunx) 使用cut截 取出Ubuntu用户的家目录,要求:不能使用“:“作为分割.

使用cut截 取出Ubuntu用户的家目录&#xff0c;要求&#xff1a;不能使用":"作为分割

spawnsync pnpm.cmd enoent

解决&#xff1a; 安装pnpm npm install pnpm -g

深入解析JDK 8 HashMap

HashMap 简介 HashMap 主要用来存放键值对&#xff0c;它基于哈希表的 Map 接口实现&#xff0c;是常用的 Java 集合之一&#xff0c;是非线程安全的。 HashMap 可以存储 null 的 key 和 value&#xff0c;但 null 作为键只能有一个&#xff0c;null 作为值可以有多个 JDK1.8…

自从学会了ChatGPT,我就再没加过班

不会吧不会吧&#xff0c;竟然还有程序员没学会ChatGPT&#xff1f;据说早学会ChatGPT的程序员已经开挂了&#xff01; 不仅实现了按时下班的人生理想&#xff0c;还拥有了升职加薪的意外收获&#xff0c;在开挂人生的另一边却仍有人担心自己会被ChatGPT取代&#xff01;因为C…

【高阶数据结构】红黑树 {概念及性质;红黑树的结构;红黑树的实现;红黑树插入操作详细解释;红黑树的验证}

红黑树 一、红黑树的概念 红黑树&#xff08;Red Black Tree&#xff09; 是一种自平衡二叉查找树&#xff0c;在每个结点上增加一个存储位表示结点的颜色&#xff0c;可以是Red或Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制&#xff0c;红黑树确保没有…

A145-FR04HS-60变量柱塞泵控制比例放大器

本比例放大器驱动电比例泵、比例压力阀、比例流量阀、比例减压阀、比例方向阀、比例插装阀、比例溢流阀、比例节流阀、比例换向阀控制。 输入指令、最大、最小电流、上升、下降斜坡时间、颤振频率等可现场设置&#xff1b; 带数码显示&#xff0c;可查看设置参数及故障报警提…

vue-cli中总提示组件没有正确注册

这里写目录标题 一、报错提示二、修改办法 一、报错提示 二、修改办法 <template><div><aside-component style"width: 15%"></aside-component></div> </template><script> import AsideComponent from /components/Asi…

JAVA毕业设计096—基于Java+Springboot+Vue的在线教育系统(源码+数据库+18000字论文)

基于JavaSpringbootVue的在线教育系统(源码数据库18000字论文)096 一、系统介绍 本系统前后端分离 本系统分为管理员、用户两种角色(管理员角色权限可自行分配) 用户功能&#xff1a; 注册、登录、课程预告、在线课程观看、学习资料下载、学习文章预览、个人信息管理、消息…

06-JVM对象内存回收机制深度剖析

上一篇&#xff1a;05-JVM内存分配机制深度剖析 堆中几乎放着所有的对象实例&#xff0c;对堆垃圾回收前的第一步就是要判断哪些对象已经死亡&#xff08;即不能再被任何途径使用的对象&#xff09;。 1.引用计数法 给对象中添加一个引用计数器&#xff0c;每当有一个地方引…

最新暴力破解漏洞技术详解

暴力破解漏洞简介 暴力破解漏洞的产生是由于服务器端没有做限制&#xff0c;导致攻击者可以通过暴力的手段破解所需信息&#xff0c;如用户名、密码、短信验证码等。暴力破解的关键在于字典的大小及字典是否具有针对性&#xff0c;如登录时&#xff0c;需要输入4位数字的短信验…

无涯教程-JavaScript - DEC2BIN函数

描述 DEC2BIN函数将十进制数转换为二进制数。 语法 DEC2BIN (number, [places])争论 Argument描述Required/Optionalnumber 要转换的十进制整数。 如果number为负数,则将忽略有效的位置值,并且DEC2BIN返回10个字符(10位)的二进制数字,其中最高有效位是符号位。其余的9位是幅…

使用多线程或异步技术提高图片抓取效率

导语 图片抓取是爬虫技术中常见的需求&#xff0c;但是图片抓取的效率受到很多因素的影响&#xff0c;比如网速、网站反爬机制、图片数量和大小等。本文将介绍如何使用多线程或异步技术来提高图片抓取的效率&#xff0c;以及如何使用爬虫代理IP来避免被网站封禁。 概述 多线…

【无监督学习之聚类】

聚类 0.简介距离 和 相似度1. K均值聚类(kmeans)模型算法特点 2. 谱聚类(Spectral clustering)算法思想特点谱聚类的具体步骤&#xff1a;算法步骤&#xff1a; 3.小结参考资料 0.简介 聚类&#xff1a;针对给定的样本&#xff0c;依据他们的属性的相似度或距离&#xff0c;将…