C++从入门到精通——命名空间
命名空间
- 前言
- 一、命名空间
- 引例
- 什么是命名空间
- 二、命名空间定义
- 正常的命名空间定义
- 嵌套的命名空间
- 多个相同名称的命名空间
- 三、命名空间使用
- 加命名空间名称及作用域限定符
- 使用`using`将命名空间中某个成员引入
- 使用`using namespace` 命名空间名称引用
- 引用命名空间和引用头文件有什么区别
前言
命名空间是一种用于封装和组织代码的结构,可以避免名称冲突并提供更好的代码组织性。在编程中,命名空间通常用于将相关的类、函数、变量等组织在一起,形成一个独立的逻辑单元。通过使用命名空间,可以更加清晰地组织代码,提高代码的可读性和可维护性。同时,命名空间也可以用于控制访问权限,保护代码的安全性和稳定性。因此,在编程中,合理地使用命名空间是一种重要的编程实践。
一、命名空间
引例
#include <stdio.h>
#include <stdlib.h>
int rand = 10;
// C语言没办法解决类似这样的命名冲突问题,所以C++提出了namespace来解决
int main()
{printf("%d\n", rand);return 0;
}
// 编译后后报错:error C2365: “rand”: 重定义;以前的定义是“函数”
为什么会出现这种情况呢?是因为在C语言中的stdlib.h
中的rand
函数和我们定义的变量冲突了,这种情况在C语言中我们只能通过改变参数的名字来解决这种情况,但是在C++完全不用担心这种情况,因为C++中有着命名空间namespace
来严格管控函数
什么是命名空间
命名空间顾名思义就是通过定义一个空间来封装变量,函数,是一种用来给变量和函数等标识符起一个独特且有组织的名称的机制。通过使用命名空间,可以避免在不同的代码模块中出现重名的标识符,从而提高代码的可读性和可维护性。
namespace bit
{……
}
在C/C++中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染,namespace
关键字的出现就是针对这种问题的。
命名空间是一个用于封装类、函数、变量等代码元素的容器,它提供了一种将相关代码组织在一起的方式,并避免了不同代码之间的命名冲突。在编程中,命名空间的存在使得代码更加清晰、有序,提高了代码的可读性和可维护性。
在C++语言中,命名空间的使用尤为普遍。通过使用命名空间,我们可以将不同模块的代码分隔开来,避免了函数和变量名称的冲突。例如,在C++标准库中,所有的标准函数和类都被定义在一个名为std
的命名空间中,这样我们在使用标准库时就需要通过std::
前缀来访问其中的元素。
除了C++,其他编程语言也提供了类似命名空间的机制。例如,在Python中,我们可以通过模块来实现类似命名空间的功能。每个模块都是一个独立的命名空间,其中包含了该模块中定义的所有函数、类和变量。当我们在其他模块中导入某个模块时,就可以通过该模块的名称来访问其中的元素,从而避免了命名冲突。
命名空间的使用不仅可以提高代码的可读性和可维护性,还可以帮助我们更好地组织和管理代码。通过将相关的代码元素放在同一个命名空间中,我们可以更加清晰地表达代码之间的逻辑关系,使得代码更加易于理解和维护。
在实际开发中,我们应该充分利用命名空间的特性,合理地组织和管理代码。同时,我们也需要注意避免过度使用命名空间,以免造成代码结构的混乱和复杂性的增加。只有在适当的时候使用命名空间,才能更好地发挥其优势,提高代码的质量和效率。
二、命名空间定义
定义命名空间,需要使用到namespace
关键字,后面跟命名空间的名字,然后接一对{}
即可,{}
中即为命名空间的成员。
ps:下文中的bit是我自己定义的,不是只能这样定义,也可以换成其他名称,名称根据自己的喜好定义即可,如果是在项目中,可以按照项目名称来定义
正常的命名空间定义
namespace bit
{// 命名空间中可以定义变量/函数/类型int rand = 10;int Add(int left, int right){return left + right;}struct Node{struct Node* next;int val;};
}
嵌套的命名空间
//命名空间可以嵌套
namespace N1
{int a;int b;int Add(int left, int right){return left + right;}namespace N2{int c;int d;int Sub(int left, int right){return left - right;}}
}
多个相同名称的命名空间
同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中。
namespace N1
{int a;int b;int Add(int left, int right){return left + right;}namespace N2{int c;int d;int Sub(int left, int right){return left - right;}}
}
namespace N1
{int Mul(int left, int right){return left * right;}
}
上面相同的命名空间将在代码的运行过程中变成下述情况(当然实际的在编译运行的时候肯定不是这样的,但实际意义是一样的,读者可以按照下述来理解)
namespace N1
{int a;int b;int Add(int left, int right){return left + right;}namespace N2{int c;int d;int Sub(int left, int right){return left - right;}}int Mul(int left, int right){return left * right;}
}
注意:一个命名空间就定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间中
三、命名空间使用
命名空间中成员该如何使用呢?
比如:
namespace bit
{// 命名空间中可以定义变量/函数/类型int a = 0;int b = 1;int Add(int left, int right){return left + right;}struct Node{struct Node* next;int val;};
}
int main()
{// 编译报错:error C2065: “a”: 未声明的标识符printf("%d\n", a);return 0;
}
为什么会出现报错呢?是因为a
已经被放到我们定义的namespace bit
中了,编译器直接查找的话是查找不到的
在这里我涉及一些编译器查找的知识,我们在同时定义一个变量的全局变量和局部变量
int a = 0;
int main()
{int a = 1;// 编译报错:error C2065: “a”: 未声明的标识符printf("%d\n", a);return 0;
}
我们可以明显看到编译器打印了局部变量,之所以打印局部变量是因为编译器查找是按照
- 局部变量
- 全局变量
这两种情况来查找的,正常情况下是没有namespace
的访问权利的,我们需要通过代码来获得访问权利,即使编译器查找变成
- 局部变量
- 全局变量
namespace
命名空间的使用有三种方式:
ps:命名空间里的未赋值的变量是随机值吗?
在许多编程语言中,命名空间中未赋值的变量通常被初始化为默认值,而不是随机值。这些默认值可能是零、空、false或null,具体取决于编程语言和变量的类型。对于数字类型的变量,通常将其初始化为零或null。对于布尔类型的变量,通常将其初始化为false。对于字符串类型的变量,通常将其初始化为空字符串。对于对象类型的变量,通常将其初始化为null。这样可以确保在使用变量之前,它们都有一个已定义的值,从而避免出现随机的不确定性。
加命名空间名称及作用域限定符
ps:我们可以
printf("%d\n", ::a);
这样a
是全局变量
int main()
{printf("%d\n", N::a);//打印嵌套命名空间printf("%d\n", N::N1::a);return 0;
}
这样打印的是名称为N
命名空间里的a
变量
使用using
将命名空间中某个成员引入
直接使用using
可以便于不需要每次都打印N::b
using N::b;
int main()
{printf("%d\n", N::a);printf("%d\n", b);return 0;
}
使用using namespace
命名空间名称引用
直接引用N
,N
会成为上述所说的第三查找标准
using namespce N;
int main()
{printf("%d\n", N::a);printf("%d\n", b);Add(10, 20);return 0;
}
引用命名空间和引用头文件有什么区别
在C++编程中,引用命名空间和引用头文件是两个常见的概念,它们各自承担着不同的角色,并在编程过程中发挥着不可或缺的作用。虽然它们都与代码的组织和重用有关,但它们的用途和效果却有所不同。
首先,引用命名空间(using namespace)主要是为了解决命名冲突和简化代码书写。在大型项目中,不同的库和模块可能会使用相同的名称来命名不同的函数或类。为了避免这种命名冲突,C++引入了命名空间的概念。通过引用命名空间,我们可以告诉编译器我们希望使用哪个命名空间中的名称,从而避免因为名称冲突而导致的编译错误。例如,当我们在代码中写using namespace std;
时,我们就告诉编译器我们想使用标准库中的所有名称,而不需要在每次调用标准库函数或类时都加上std::
前缀。
而引用头文件(#include)则是C++中实现代码重用和模块化编程的重要手段。头文件通常包含了类的声明、函数的原型、常量定义等,它们可以被多个源文件共享和引用。通过引用头文件,我们可以实现代码的模块化,使得每个模块只关心自己的功能实现,而不必关心其他模块的实现细节。这样不仅可以提高代码的可读性和可维护性,还可以提高编译效率,因为编译器只需要编译那些被实际引用的头文件和源文件。
虽然引用命名空间和引用头文件在C++编程中有着不同的作用,但它们在实际应用中往往是相辅相成的。例如,在一个头文件中,我们可能会定义一些属于特定命名空间的函数或类。当其他源文件需要使用这些函数或类时,它们不仅需要引用这个头文件,还需要引用相应的命名空间。这样,通过引用头文件和命名空间,我们就可以在不同的源文件之间共享和重用代码,同时避免命名冲突和简化代码书写。
综上所述,引用命名空间和引用头文件在C++编程中各有其独特的作用。引用命名空间主要用于解决命名冲突和简化代码书写,而引用头文件则主要用于实现代码重用和模块化编程。通过合理地使用它们,我们可以编写出更加高效、可读和可维护的C++代码。
相关文章:

C++从入门到精通——命名空间
命名空间 前言一、命名空间引例什么是命名空间 二、命名空间定义正常的命名空间定义嵌套的命名空间多个相同名称的命名空间 三、命名空间使用加命名空间名称及作用域限定符使用using将命名空间中某个成员引入使用using namespace 命名空间名称引用引用命名空间和引用头文件有什…...
JAVA面试大全之JAVA新特性篇
目录 1、Java 8特性 1.1、什么是函数式编程?Lambda表达式? 1.2、Stream中常用方法? 1.3、什么是FunctionalInterface? 1.4、如何自定义函数接口?...
【ZZULIOJ】1008: 美元和人民币(Java)
目录 题目描述 输入 输出 样例输入 Copy 样例输出 Copy code 题目描述 美元越来越贬值了,手上留有太多的美元似乎不是件好事。赶紧算算你的那些美元还值多少人民币吧。假设美元与人民币的汇率是1美元兑换6.5573元人民币,编写程序输入美元的金额&a…...
LeetCode刷题笔记之动态规划(三)
一、子序列/子数组问题 子序列:按原数组的顺序排列,不一定是原数组中的相邻元素组成的。即子序列可以是不连续的。 子数组:原数组中连续的几个元素组成的数组。 1. 300【最长递增子序列】 题目: 给你一个整数数组 nums ÿ…...

Unity编辑器功能将AB资源文件生成MD5码
将路径Application.dataPath/ArtRes/AB/PC文件夹下所有的Ab包文件生成MD5吗,通过文件名 文件长度MD5‘|’的格式拼接成字符串写入到资源对比文件abCompareInfo.txt中。 将路径pathFile扥文件生成MD5码...

【案例·增】获取当前时间、日期(含,SQL中DATE数据类型)
问题描述: 需要使用当前时间、日期,可以使用 SQL 中的 CURDATE() 、NOW()、CURTIME()运算符 案例: INSERT INTO table_name(current_time, column_name2,...) VALUES (NOW(),, ...)规则(Date 相关函数): 规则(Date数据类型)...
什么是回调函数?回调函数有什么缺点?如何解决回调地狱问题?
什么是回调函数?回调函数有什么缺点?如何解决回调地狱问题? 以下代码就是一个回调函数的例子: ajax(url, () > {// 处理逻辑 })回调函数有一个致命的弱点,就是容易写出回调地狱(Callback hell࿰…...

如何在Linux系统使用Docker本地部署Halo网站并实现无公网IP远程访问
最近,我发现了一个超级强大的人工智能学习网站。它以通俗易懂的方式呈现复杂的概念,而且内容风趣幽默。我觉得它对大家可能会有所帮助,所以我在此分享。点击这里跳转到网站。 文章目录 1. Docker部署Halo1.1 检查Docker版本如果未安装Docker可…...
智能写作利器ChatGPT:提升论文写作效率
ChatGPT无限次数:点击直达 智能写作利器ChatGPT:提升论文写作效率 在当今信息爆炸的时代,快速高效地撰写论文对于科研工作者来说至关重要。智能写作工具ChatGPT的出现为我们提供了强大的支持,它不仅能够提升论文写作的效率,还能够…...

【iOS ARKit】3D文字
首先,3D场景中渲染的任何虚拟元素都必须具有网格(顶点及顶点间的拓扑关系),没有网格的元素无法利用GPU 进行渲染,因此,在3D 场景申渲染 3D文字时,文字也必须具有网格。在计算机系统中࿰…...

第二百二十八回
文章目录 1. 概念介绍2. 修改方法2.1 修改形状2.2 修改颜色2.3 修改位置 3. 示例代码4. 内容总结 我们在上一章回中介绍了"如何创建以图片为背景的页面"相关的内容,本章回中将介绍如何修改按钮的形状.闲话休提,让我们一起Talk Flutter吧。 1. …...

Java设计模式之单例模式(多种实现方式)
虽然写了很多年代码,但是说真的对设计模式不是很熟练,虽然平时也会用到一些,但是都没有深入研究过,所以趁现在有空练下手 这章主要讲单例模式,也是最简单的一种模式,但是因为spring中bean的广泛应用&#…...
Miracast投屏探索
Miracast是一种Wi-Fi Alliance推出的无线显示技术,允许在支持Miracast标准的设备之间进行屏幕镜像和内容共享。在Miracast技术中,通常会涉及到两种角色:Source(发送端)和Sink(接收端)。 Source&…...

2024年幻兽帕鲁服务器优惠价格表手动整理,最全报价
2024年全网最全的幻兽帕鲁服务器租用价格表,阿里云幻兽帕鲁游戏服务器26元1个月、腾讯云32元一个月、京东云26元一个月、华为云24元1个月,阿腾云atengyun.com整理最新幻兽帕鲁专用4核16G、8核16G、8核32G游戏服务器租用价格表大全: 阿里云幻…...
使用Python自动备份重要文件:一步一步的教程
目录 1 重要性说明1.1 数据丢失的风险1.2 自动化备份的好处1.3 提高数据安全性和恢复力 2 工具和技术简介2.1 os库2.2 shutil库2.3 glob库2.4 pathlib库 3 备份策略设计3.1 全备份3.2 增量备份3.3 差异备份3.4 根据需求选择备份策略 4 编写备份脚本4.1 步骤拆解步骤 1: 选择源文…...
python学习
Python面试题大全 - 50道经典面试题 - 掘金 yoloV5:yolov5: YOLOv5 汉化版,保持官方同步更新 yoloV8使用案例:用YOLOv8一站式解决图像分类、检测、分割…… - 掘金 yoloV8使用案例douyin:https://www.douyin.com/user/self?modal_id7276287878194285…...

【使用redisson完成延迟队列的功能】使用redisson配合线程池完成异步执行功能,延迟队列和不需要延迟的队列
1. 使用redisson完成延迟队列的功能 引入依赖 spring-boot-starter-actuator是Spring Boot提供的一个用于监控和管理应用程序的模块 用于查看应用程序的健康状况、审计信息、指标和其他有用的信息。这些端点可以帮助你监控应用程序的运行状态、性能指标和健康状况。 已经有了…...
Linux 性能分析工具 perf 的使用指南
什么是perf,可以用来干什么 perf 是 Linux 内核的性能分析工具集,它可以用来监控和分析系统和应用程序的性能。perf 提供了一系列功能强大的子命令,可以帮助开发者和系统管理员: 监控 CPU 使用率:识别最消耗 CPU 的代…...

【QT入门】 Qt代码创建布局之水平布局、竖直布局详解
往期回顾: 【QT入门】 Qt实现自定义信号-CSDN博客 【QT入门】 Qt自定义信号后跨线程发送信号-CSDN博客 【QT入门】 Qt内存管理机制详解-CSDN博客 【QT入门】 Qt代码创建布局之水平布局、竖直布局详解 先看两个问题: 1、ui设计器设计界面很方便…...
C 传递数组给函数
如果您想要在函数中传递一个一维数组作为参数,您必须以下面三种方式来声明函数形式参数,这三种声明方式的结果是一样的,因为每种方式都会告诉编译器将要接收一个整型指针。同样地,您也可以传递一个多维数组作为形式参数。 方式 1…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)
笔记整理:刘治强,浙江大学硕士生,研究方向为知识图谱表示学习,大语言模型 论文链接:http://arxiv.org/abs/2407.16127 发表会议:ISWC 2024 1. 动机 传统的知识图谱补全(KGC)模型通过…...
《C++ 模板》
目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板,就像一个模具,里面可以将不同类型的材料做成一个形状,其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式:templa…...

面向无人机海岸带生态系统监测的语义分割基准数据集
描述:海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而,目前该领域仍面临一个挑战,即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...

人机融合智能 | “人智交互”跨学科新领域
本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...
Mysql8 忘记密码重置,以及问题解决
1.使用免密登录 找到配置MySQL文件,我的文件路径是/etc/mysql/my.cnf,有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...

群晖NAS如何在虚拟机创建飞牛NAS
套件中心下载安装Virtual Machine Manager 创建虚拟机 配置虚拟机 飞牛官网下载 https://iso.liveupdate.fnnas.com/x86_64/trim/fnos-0.9.2-863.iso 群晖NAS如何在虚拟机创建飞牛NAS - 个人信息分享...
【学习笔记】erase 删除顺序迭代器后迭代器失效的解决方案
目录 使用 erase 返回值继续迭代使用索引进行遍历 我们知道类似 vector 的顺序迭代器被删除后,迭代器会失效,因为顺序迭代器在内存中是连续存储的,元素删除后,后续元素会前移。 但一些场景中,我们又需要在执行删除操作…...

Mac flutter环境搭建
一、下载flutter sdk 制作 Android 应用 | Flutter 中文文档 - Flutter 中文开发者网站 - Flutter 1、查看mac电脑处理器选择sdk 2、解压 unzip ~/Downloads/flutter_macos_arm64_3.32.2-stable.zip \ -d ~/development/ 3、添加环境变量 命令行打开配置环境变量文件 ope…...
Yii2项目自动向GitLab上报Bug
Yii2 项目自动上报Bug 原理 yii2在程序报错时, 会执行指定action, 通过重写ErrorAction, 实现Bug自动提交至GitLab的issue 步骤 配置SiteController中的actions方法 public function actions(){return [error > [class > app\helpers\web\ErrorAction,],];}重写Error…...

项目进度管理软件是什么?项目进度管理软件有哪些核心功能?
无论是建筑施工、软件开发,还是市场营销活动,项目往往涉及多个团队、大量资源和严格的时间表。如果没有一个系统化的工具来跟踪和管理这些元素,项目很容易陷入混乱,导致进度延误、成本超支,甚至失败。 项目进度管理软…...