命名冲突问题与命名空间
一、何为命名空间?
首先我们运行下面代码,
#include <stdio.h>
int rand = 0;
int main()
{printf("%d", rand);return 0;
}
我们会发现该代码能够正常运行,没有任何问题。
但是当我们再在上面代码的基础上包含stdlib.h头文件,代码还能正常运行吗?
#include <stdio.h>
#include <stdlib.h>
int rand = 0;
int main()
{printf("%d", rand);return 0;
}
这时我们会发现代码报错——“rand”重定义。这是因为在stdlib.h头文件中已经定义了rand()函数,与全局变量rand发生了命名冲突问题,从而导致printf()函数无法确定是输出rand全局变量的值还是输出rand()函数的地址。
在日常写代码的过程中,我们自己定义的变量、函数很有可能跟C++库发生命名冲突问题。并且进入公司项目组以后,做的项目通常比较大,多人协作也很有可能造成命名冲突问题。
但是C语言没有办法很好地解决这个问题,若非要有办法的话,也就只能是给重名的定义更换其他名字。
但这样做会导致工作效率十分低下,为了更高效地解决此问题,C++提出了一个新语法——命名空间。
在C/C++中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染,namespace关键字的出现就是针对这种问题的。
二、命名空间定义
定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接一对{}即可,{}中即为命名空间的成员。
如下面代码:
#include <stdio.h>
#include <stdlib.h>namespace zjd // zjd为命名空间的的名称
{int rand = 0;
}int main()
{
// rand先到局部范围内找,若没有再到全局范围内找,若还没有则程序会报错,不会到定义的域里面去找printf("%d\n", rand); // rand访问的是全局变量,rand()函数// rand指定到定义的zjd域里面去找printf("%d\n", zjd::rand); // ::域作用限定符return 0;
}
该代码定义了一个名为zjd的命名空间(域),与全局作用域进行了隔离,不会发生命名冲突问题。
Note:
①命名空间定义和结构体定义写法类似但又不同,结构体定义了一个新的数据类型,命名空间定义了一个新的域。
②域作用限定符(::)
当域作用限定符(::)前面指定域名时,会到指定的域中寻找变量、函数和类。
当域作用限定符(::)前面为空白时,会到全局域中寻找变量、函数和类。
当没有域作用限定符(::)前面指定域名时,会依次到局部域、全局域中寻找变量、函数和类。若局部域和全局域都没有找到,程序会报错。
int a = 0; int main() {int a = 1;printf("%d\n", a); // 输出局部变量a —— 1printf("%d\n", ::a); // 输出全局变量a —— 0return 0; }③一个命名空间就定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间中。
1、普通的命名空间
命名空间中的内容,既可以定义变量,也可以定义函数,还可以定义类型。
namespace N1
{int rand; // 变量int Add(int left, int right) // 函数{return left + right;}struct Node // 类型{struct Node* next;int val;};
}int main()
{N1::a = 10;printf("%d\n", N1::a);int sum = N1::Add(1, 2);printf("%d\n", sum);struct N1::Node node;return 0;
}
2、命名空间可以嵌套
命名空间内部还可以嵌套定义命名空间。
namespace N2
{int a;int b;int Add(int left, int right){return left + right;}namespace N3{int c;int d;int Sub(int left, int right){return left - right;}}
}int main()
{int sum = N2::Add(1, 2);printf("%d\n", sum);int dif = N2::N3::Sub(2, 1);printf("%d\n", dif);return 0;
}
3、多个命名空间名称相同
同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中。
比如一个工程中的test.h和test.cpp中两个同名的命名空间会被合并成一个。
// Test.h
namespace N4
{typedef struct ListNode{struct ListNode* next;int val;}ListNode, * LinkList;void ListInit(LinkList ps); // 声明void ListPushBack(LinkList ps, int x); // 声明
}// Test.cpp
#include"Test.h"
namespace N4
{void ListInit(LinkList ps) // 定义{// 实现不展开写了}void ListPushBack(LinkList ps, int x) // 定义{// 实现不展开写了}
}int main()
{struct N4::ListNode node;N4::ListInit(&node);N4::ListPushBack(&node, 3);return 0;
}
三、命名空间使用
命名空间中成员该如何使用呢?比如下面代码是正确的代码吗?
namespace N
{int a = 10;int b = 20;int Add(int left, int right){return left + right;}int Sub(int left, int right){return left - right;}
}
int main()
{printf("%d\n", a); // 该语句编译出错,无法识别areturn 0;
}
由于局部域和全局域都没有a,并且未通过域作用限定符指定a的域,无法识别a,所以上面代码无法正常运行。
命名空间的使用有三种方式:
- 加命名空间名称及作用域限定符
- 使用using将命名空间中成员引入
- 使用using namespace 命名空间名称引入
1、加命名空间名称及作用域限定符
在命名空间定义的讲解中,大家实际上已经掌握该方式的使用了。
namespace N
{int a = 10;int b = 20;int Add(int left, int right){return left + right;}int Sub(int left, int right){return left - right;}
}int main()
{printf("%d\n", N::a);return 0;
}
Note:该方式能够做到最好的命名隔离,但是使用不方便,每次都需要指定域。
2、使用using将命名空间中成员引入
通过该方式我们可以将命名空间的某个成员展开,被展开的成员无需再通过域作用限定符指定域,但是未被展开的成员仍需要通过域作用限定符指定域。
namespace N
{int a = 10;int b = 20;int Add(int left, int right){return left + right;}int Sub(int left, int right){return left - right;}
}using N::b;int main()
{printf("%d\n", N::a);printf("%d\n", b);return 0;
}
Note:该方式可以用于展开常用的成员,也有较好的隔离效果。
3、使用using namespace 命名空间名称引入
通过该方式我们可以将整个命名空间展开,使用该命名空间里的变量、函数等无需再通过域作用限定符指定域了。
namespace N
{int a = 10;int b = 20;int Add(int left, int right){return left + right;}int Sub(int left, int right){return left - right;}
}using namespace N;int main()
{printf("%d\n", a);printf("%d\n", b);Add(10, 20);return 0;
}
Note:命名空间全部展开,用起来虽然极其方便,但是隔离彻底失效了。这种方式建议大家慎用。
相关文章:
命名冲突问题与命名空间
一、何为命名空间? 首先我们运行下面代码, #include <stdio.h> int rand 0; int main() {printf("%d", rand);return 0; } 我们会发现该代码能够正常运行,没有任何问题。 但是当我们再在上面代码的基础上包含stdlib.h头…...
Kafka漏洞修复之CVE-2023-25194修复措施验证
Kafka漏洞修复之CVE-2023-25194修复措施验证前言风险分析解决方案AdoptOpenJDK Zookeeper Kafka多版本OpenJDK安装切换Zookeeper安装Kafka安装与使用其他Kafka消息发送流程Linux配置加载顺序参考链接前言 场景介绍 Kafka最近爆出高危漏洞CNNVD-202302-515,导致Apa…...
中后序遍历构建二叉树与应用I
目录 题目描述 思路分析 AC代码 题目描述 按中序遍历和后序遍历给出一棵二叉树,求这棵二叉树中叶子节点权值的最小值。 输入保证叶子节点的权值各不相同。 输入 测试数据有多组 对于每组测试数据,首先输入一个整数N (1 < N < 10000)&#x…...
随机退化模型--基础篇(1)
随机退化模型--基础篇(1) 1. 随机退化建模1.1 瞬间失效1.2 存在缓慢退化过程的失效2. 通俗解释2.1 包引入2.2 参数定义2.3 基于递归函数的更新2.4 结果可视化1. 随机退化建模 随机模型亦称“非确定的、概率的模型”,是按随机变量建立的模型。其特点是; 模型参数、模拟对象发…...
2023.2.15工作学习记录 git Docker compose容器编排
关于Git错误提交了target目录 是因为在ignore目录中没有加入biz这个工程 以后提交代码时一定要检查好自己提交的代码 首先把所有的全部取消 然后再根据自己要提交的内容一个个来勾选 Docker网络 container模式:新建的容器和已经存在的一个容器共享一个网络…...
基于jeecgboot的flowable流程增加节点自动跳过功能
为了满足有时候需要在某个节点没有人员处理的时候需要自动跳过,所以增加了这个功能。 一、FlowComment意见里增加一个类型8,跳过流程 /** * 流程意见类型 * */ public enum FlowComment { /** * 说明 */ NORMAL("1", "…...
流程引擎之Activiti简介
背景Activiti 是一个开源架构的工作流引擎,基于 bpmn2.0 标准进行流程定义,其前身是 jBPM,Activiti 相对于 jBPM 更轻量,更易上手,且天然集成了 Spring。2010年 jBPM 创始人 Tom Baeyens 离开 JBoss,随之加…...
4.打包子应用 投票
接上回 最终得到这样的目录 mysite/manage.pymysite/__init__.pysettings.pyurls.pyasgi.pywsgi.pypolls/__init__.pyadmin.pyapps.pymigrations/__init__.py0001_initial.pymodels.pystatic/polls/images/background.gifstyle.csstemplates/polls/detail.htmlindex.htmlresult…...
华为OD机试 - 服务依赖(JavaScript) | 机试题算法思路 【2023】
服务依赖 题目 在某系统中有众多服务,每个服务用字符串(只包含字母和数字,长度<=10)唯一标识,服务间可能有依赖关系,如A依赖B,则当B故障时导致A也故障。 传递具有依赖性,如A依赖B,B依赖C,当C故障时导致B故障,也导致A故障。给出所有依赖关系以及当前已知故障服务…...
目标检测综述(一份全的自制PPT): 涵盖各种模型简介对比,适合入门和了解目标检测现状
[TOC](目标检测综述(一份全的自制PPT): 涵盖各种模型简介对比,适合入门和了解目标检测现状) 注:本文仅供学习,未经同意勿转。分享的PPT请勿二次传播,或者用于其他商用途径。若使用本文PPT请注明来源,感谢配合 前言&…...
Vulnhub-DC-2实战靶场
Vulnhub-DC-2实战靶场 https://blog.csdn.net/ierciyuan/article/details/127560871 这次试试DC-2,目标是找到官方设置的5个flag。 一. 环境搭建 1. 准备工具 虚拟机Kali: 自备,我的kali的IP为192.168.3.129 靶场机: https…...
从输入URL到渲染的过程中到底发生了什么?
CDN缓存DNSTCP三次握手、四次挥手浏览器渲染过程输入URL到页面渲染过程的一些优化 下面我将“从输入URL到渲染的全过程”大概的描述出来,再对其过程加以解释,了解过程中可以做哪些优化。文章内容有点长,需要有足够的耐心看完哟!&…...
旋转屏幕导致 Fragment 中的 onConfigurationChanged 被调用两次
环境 IDE Android Studio Dolphin 2021.3.1; 项目配置 Android Gradle plugin version: 7.1.3 Gradle Version: 7.2 Gradle JDK: 11 Compile Sdk Version: 32 问题描述 项目使用的 Bottom Navigation Activity 基本结构,在调试程序时发现,…...
23年校招DL/NLP/推荐系统/ML/算法基础面试必看300问及答案
2020年校招已经开始了,在疫情全球肆虐的背景下,全球就业情况异常艰难,加上美国对中国企业打压持续升级,对于马上开始秋招找工作的毕业生而言,更是难上加难。我们不能凭一己之力改变现状,但我们可以凭借自己…...
Python基础知识汇总(字符串二)
目录 检索字符串 count()方法 find()方法 in关键字 index()方法 rindex()方法 startswith()方法...
【FPGA】Verilog:实现十六进制七段数码管显示 | 7-Segment Display
写在前面:本章主要内容为理解七点数码管显示的概念,并使用 Verilog 实现。生成输入信号后通过仿真确认各门的动作,通过 FPGA 检查在 Verilog 中实现的电路的操作。 Ⅰ. 前置知识 七段数码管是利用多重输出功能的非常有用的元件。该元件用于字…...
Android开发:Activity启动模式
1.怎样设置Activity的启动模式 可以在清单文件中自己添加活动的启动模式, android : launchMode"standard", 不写的话系统默认就是标准模式. 2.启动模式 2.1.默认启动模式 标准启动模式就是栈, 打开一个活动就将活动压入栈中, 返回就将活动退出栈中. 不同的Activit…...
01_Docker 简介
01_Docker 简介 文章目录01_Docker 简介1.1 Docker 简介1.2 Docker 组件1.2.1 Docker 客户端和服务区1.2.2 Docker 镜像1.2.3 Registry1.2.4 Docker 容器参考资料https://www.runoob.com/docker/ubuntu-docker-install.html 1.1 Docker 简介 Docker 是一个能够把开发的应用程…...
一文精通MVCC机制
MVCC(Multi-Version Concurrency Control)多版本并发控制机制使用串行化隔离级别时,mysql会将所有的操作加锁互斥,来保证并发安全。这种方式必然降低并发性能。mysql在读已提交和可重复读隔离级别下,对一行数据的读和写两个操作默认是不会通过…...
商用ESP32协议采集器源码分享开篇
这是一个关于chatGPT帮助嵌入式程序员开发商业项目的故事. 在开发这个项目的过程中,chatGPT发布了,在它的帮助下,项目开发量减少了10%,所以这个专栏,既是一个关于Micropython开发ESP32的专栏,也是一个程序员在AI的帮助下,提升效率,加速挣钱的案例. 看完之后,你将知道如何用mic…...
从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路
进入2025年以来,尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断,但全球市场热度依然高涨,入局者持续增加。 以国内市场为例,天眼查专业版数据显示,截至5月底,我国现存在业、存续状态的机器人相关企…...
(二)原型模式
原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...
涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战
“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...
python报错No module named ‘tensorflow.keras‘
是由于不同版本的tensorflow下的keras所在的路径不同,结合所安装的tensorflow的目录结构修改from语句即可。 原语句: from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后: from tensorflow.python.keras.lay…...
NPOI操作EXCEL文件 ——CAD C# 二次开发
缺点:dll.版本容易加载错误。CAD加载插件时,没有加载所有类库。插件运行过程中用到某个类库,会从CAD的安装目录找,找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库,就用插件程序加载进…...
Web后端基础(基础知识)
BS架构:Browser/Server,浏览器/服务器架构模式。客户端只需要浏览器,应用程序的逻辑和数据都存储在服务端。 优点:维护方便缺点:体验一般 CS架构:Client/Server,客户端/服务器架构模式。需要单独…...
区块链技术概述
区块链技术是一种去中心化、分布式账本技术,通过密码学、共识机制和智能合约等核心组件,实现数据不可篡改、透明可追溯的系统。 一、核心技术 1. 去中心化 特点:数据存储在网络中的多个节点(计算机),而非…...
VisualXML全新升级 | 新增数据库编辑功能
VisualXML是一个功能强大的网络总线设计工具,专注于简化汽车电子系统中复杂的网络数据设计操作。它支持多种主流总线网络格式的数据编辑(如DBC、LDF、ARXML、HEX等),并能够基于Excel表格的方式生成和转换多种数据库文件。由此&…...
Sklearn 机器学习 缺失值处理 获取填充失值的统计值
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 使用 Scikit-learn 处理缺失值并提取填充统计信息的完整指南 在机器学习项目中,数据清…...
【UE5 C++】通过文件对话框获取选择文件的路径
目录 效果 步骤 源码 效果 步骤 1. 在“xxx.Build.cs”中添加需要使用的模块 ,这里主要使用“DesktopPlatform”模块 2. 添加后闭UE编辑器,右键点击 .uproject 文件,选择 "Generate Visual Studio project files",重…...
