【C++】用命名空间避免命名冲突

  • 🌸博主主页:@釉色清风
  • 🌸文章专栏:C++
  • 🌸今日语录:如果神明还不帮你,说明他相信你。
  • 🪷文章简介:这篇文章是结合谭浩强老师的书以及自己的理解,同时加入了一些例子,方便理解。希望对大家有帮助。

用命名空间避免命名冲突

  • 🌼名字冲突问题
    • 🌻例子
    • 🌻名字冲突
  • 🌼命名空间
    • 🌻命名空间的类型
    • 🌻命名空间的成员
    • 🌻命名空间的使用
  • 🌼使用命名空间解决名字冲突

🌼名字冲突问题

在实际生活中,一个大型的项目往往不是一个人独立完成的,而是由若干个人合作完成的,不同的人分别完成不同的部分,最后组合成一个完整的程序。

假如不同的人分别定义了类,放在不同的头文件中,在主文件(包含主函数的文件)需要用这些类时,就用#include指令将这些头文件包含进来。

由于各头文件是由不同的人设计的,有可能在不同的头文件中用了相同的名字来命名所定义的类或函数。这样在程序中就会出现名字冲突

🌻例子

程序员甲在头文件header1.h中定义了类Student和函数fun:

#pragma once
//header1.h
#include <iostream>
#include<string>
#include <cmath>
using namespace std;
class Student //声明Student类
{
public:Student(int n, string nam, int a){num = n;name = nam;age = a;}void get_data();
private:int num;string name;int age;
};
//成员函数的定义
void  Student::get_data()
{cout<< num <<"" << name << "" << age << endl;
}
//定义全局函数(即外部函数)
double fun(double a, double b)
{return sqrt(a + b);
}

在main函数所在的主文件中包含文件header1.h:

#include "header1.h"
int main()
{Student stud1(101,"Wang",18);stud1.get_data;cout<<fun(5,3)<<endl;return 0;
}

运行结果如下:

如果程序员乙写了头文件head2.h,在其中定义了其他类以外,还定义了类Student和函数fun,但其内容与头文件header1.h中的Student和函数fun有所不同。

//header2.h
#pragma once
#include <string.h>
#include<cmath>
#include<iostream>
using namespace std;
class Student
{
public:Student(int n, string nam, char s)//参数与header1.h中不同{num = n;name = nam;sex = s;}void get_data();
private:int num;string name;char sex;
};//成员函数定义
void Student::get_data()
{cout << num << "" << name << "" << sex << endl;
}
//定义全局函数
double fun(double a, double b)
{return sqrt(a - b);//返回值与header1中的fun函数不同
}
......
//头文件2可能还有其他的内容

假如主程序员在其程序中要用到header1.h中的Student和函数fun,因而在程序中包含了头文件header1.h,同时又要用到头文件header2.h中的一些内容,但是不知道此时header2.h中包含了与header1.h同名单内容不同的Student类和fun函数,因而又在头文件中包含了头文件header2.h。

主文件如下:

//main file
#include <iostream>
#include "header1.h"
#include "header2.h"int main()
{Student stud1(101,"Wang",18);stud1.get_data;cout<<fun(5,3)<<endl;return 0;
}

这时,程序编译就会出现错误。

🌻名字冲突

因为在预编译后,头文件中的内容取代了对应的#include指令,这样就在同一个程序文件中出现了两个Student类和两个fun函数,显然是重复定义,这就是名字冲突。
名字冲突,即在同一个作用域中含有两个或多个同名的实体。
不仅如此,在程序中往往还需要引用一些库,包括C++编译系统提供的库、由软件开发商提供的库或者用户自己开发的库,为此需要包含有关的头文件。如果在这些库中包含有与程序的全局实体同名的实体,或者不同的库中有相同的实体名,则在编译时就会出现名字冲突。有人称之为全局命名空间污染

为了避免这类问题的出现,人们提出了许多方法,例如:将实体的名字写得长一点(包含十几个或几十个字母和字符);把名字搞得特殊一些,包括一些特殊的字符;由编译系统提供的内部全局标识符都用下划线作为前缀,如_complex(),以避免与用户的实体同名;由软件开发商提供的尸体的名字用特定的字符作为前缀等。但是这样的效果并不理想,而且增加了阅读程序的难度,即可读性降低了。

C语言和早期的C++语言没有提供有效的机制来解决这个问题,没有库的提供者能够建立自己的命名空间。人们希望ANSI C++ 标准库能够解决这个问题,提供一种机制、一种工具,使由库的设计者命名的全局标识符能够和程序的全局实体名以及其他类的全局标识符区别开来。

🌼命名空间

为了解决这个问题,ANSI C++增加了命名空间。
所谓命命名空间,就是一个由程序设计者命名的内存区域。程序设计者可以根据需要指定一些有名字的空间域,把一些全局实体分别放在各个命名空间中,从而与其他全局实体分离开来。
我的理解就是原来我们的全局实体变量都是“暴露出来”的,然后命名空间的作用就是分别个你需要的全局实体“围起来”,像栅栏一样,每一块区域都有一个专属于自己的名字。然后在编译阶段,就像是好多个“围起来的栅栏”,且各不相同。

命名空间的作用是建立一些互相分隔的作用域,把一些全局实体分隔开来,以免产生名字冲突。

这里有一段很形象的描述,可以帮助大家更好地理解:
例如,某中学高三年级有3个叫李相国的学生,如果都在同一班,那么老师点名叫李相国时,3个人都站起来应答,这就是名字冲突。因为他们无法辨别老师想叫的是哪一个李相国?同名者无法互相区分。为了避免同名混淆,学校把3个同名的学生分在3个班。这样,在小班点名叫李相国时,只会有一个人应答。也就是说,在该班的范围内,即班作用域内名字是唯一的。如果在全校集合时校长点名,需要在全校范围内找这个学生,要考虑的作用域是全校范围。如果校长叫李相国,全校学生中又会有3个人一齐喊“到”,因为在同一作用域中存在3个同名学生。为了在全校范围内区分这3名学生,即加上班名限定。这样就不会产生混淆。

可以根据需要设置许多个命名空间,每个命名空间代表一个不同的命名空间域,不同的命名空间不能同名。这样,可以把不同的库中的实体放到不同的命名空间中,或者说,用不同的命名空间把不同的实体隐藏起来。过去用的全局变量可以理解为存在于全局命名空间,独立域所有有名的命名空间之外,不是不需要namespace声明的,实际上是由系统隐式声明的,在该空间中有效。

🌻命名空间的类型

在声明一个命名空间时,花括号内不仅可以包括变量,而且还可以包括一下类型:

  • 变量(可以带有初始化);
  • 常量;
  • 函数(可以是定义或声明);
  • 结构体;
  • 类;
  • 模板;
  • 命名空间(在一个命名空间中又定义了一个命名空间,即嵌套的命名空间)。

🌻命名空间的成员

例如:

namespace ns1 //指定命名空间ns1
{int a;double b;
}
  • ns1是命名空间的名字。
  • 在花括号内,声明的实体即为命名空间的成员,包括全局变量a和b。
  • 使用a和b,需要加上命名空间和作用域分辨符"::",如ns1::a,ns1::b。
  • 需要注意的是,a和b仍然是全局变量,仅仅是把他们放在了命名空间中而已。

🌻命名空间的使用

举例如下:

namespace ns1
{const int RATE=0.08;//常量double pay;//变量double tax()//函数{return a*RATE;}namespace ns2 //嵌套命名空间int age;}

输出命名空间中ns1中成员的数据:

cout<<ns1::RATE<<endl;
cout<<ns1::pay<<endl;
cout<<ns1::tax()<<end;
cout<<ns1::ns2::age<<endl;

🌼使用命名空间解决名字冲突

声明命名空间ns1,并在命名空间ns1中声明Student类和定义成员函数、定义fun函数。

#pragma once
//header1.h
#include <iostream>
#include<string>
#include <cmath>
using namespace std;
namespace ns1 {class Student //声明Student类{public:Student(int n, string nam, int a){num = n;name = nam;age = a;}void get_data();private:int num;string name;int age;};//成员函数的定义void  Student::get_data(){cout << num << "" << name << "" << age << endl;}//定义全局函数(即外部函数)double fun(double a, double b){return sqrt(a + b);}
}

在header2.h中,声明命名空间ns2,并在命名空间ns2中定义Student类和 成员函数以及fun函数。

using namespace std;
namespace ns2
{class Student{public:Student(int n, string nam, char s)//参数与header1.h中不同{num = n;name = nam;sex = s;}void get_data();private:int num;string name;char sex;};//成员函数定义void Student::get_data(){cout << num << "" << name << "" << sex << endl;}//定义全局函数double fun(double a, double b){return sqrt(a - b);//返回值与header1中的fun函数不同}
}

主函数如下:

#include "header1.h";
#include "header2.h";
int main()
{ns1::Student stud1(101, "Wang", 18);//用命名空间ns1中的Student类定义stud1stud1.get_data();cout <<ns1:: fun(5, 3) << endl;//调用命名空间ns1中的fun函数ns2::Student stud2(102, "Li", 'f');//用命名空间ns2中的Student类定义stud2stud2.get_data();cout << ns2::fun(5, 3) << endl;//调用命名空间ns2中的fun函数return 0;
}

运行结果如下:

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

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

相关文章

NOC2023软件创意编程(学而思赛道)python小高组初赛真题

软件创意编程 一、参赛范围 1.参赛组别:小学低年级组(1-3 年级)、小学高年级组(4-6 年级)、初中组。 2.参赛人数:1 人。 3.指导教师:1 人(可空缺)。 4.每人限参加 1 个赛项。 组别确定:以地方教育行政主管部门(教委、教育厅、教育局) 认定的选手所属学段为准。 二、…

MATLAB知识点:if条件判断语句的嵌套

​讲解视频&#xff1a;可以在bilibili搜索《MATLAB教程新手入门篇——数学建模清风主讲》。​ MATLAB教程新手入门篇&#xff08;数学建模清风主讲&#xff0c;适合零基础同学观看&#xff09;_哔哩哔哩_bilibili 节选自​第4章&#xff1a;MATLAB程序流程控制 我们通过一个…

基于springboot+vue的教师工作量管理系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

Java集合-Map接口

在Java中&#xff0c;Map接口表示键值对的集合&#xff0c;其中每个键都是唯一的&#xff0c;并且每个键映射到一个值。Map接口是集合框架中的一部分&#xff0c;位于java.util包中。它定义了一系列操作来管理键值对&#xff0c;例如添加键值对、删除键值对、获取键对应的值等。…

7.1.1 selenium介绍及安装chromedriver

目录 1. Selenium的用途 2. 安装Selenium库 3. 安装chromedriver 1. 查看谷歌版本号​编辑 2. 找到最新版本及下载 3. 配置环境变量 4. 检测是否配置成功 5. 用python初始化浏览器对象检测&#xff1a; 6. 参考链接 1. Selenium的用途 在前面我们提到&#xff1a;在我…

Github项目推荐-LightMirrors

项目地址 https://github.com/NoCLin/LightMirrors 项目简述 “LightMirrors是一个开源的缓存镜像站服务&#xff0c;用于加速软件包下载和镜像拉取。目前支持DockerHub、PyPI、PyTorch、NPM等镜像缓存服务。 当前项目仍处于早期阶段。”–来自项目说明。 也就是说&#xff…

RocketMq——Consume相关源码

摘要 RocketMQ只要有CommitLog文件就可以正常运行了&#xff0c;那为何还要维护ConsumeQueue文件呢&#xff1f; ConsumeQueue是消费队列&#xff0c;引入它的目的是为了提高消费者的消费速度。毕竟RocketMQ是基于Topic主题订阅模式的&#xff0c;消费者往往只关心自己订阅的…

定制开发一款家政小程序,应知应会

引言 在这个快节奏的现代生活中&#xff0c;人们对高效、便捷的家政服务的需求日益增加。随着社会结构的变化和职业生活的繁忙&#xff0c;许多家庭面临着时间不足、精力不济的挑战。在这种情况下&#xff0c;家政服务成为解决问题的有效途径。然而&#xff0c;传统的家政服务…

Python——桌面摄像头软件(附源码+打包)

目录 一、前言 二、桌面摄像头软件 2.1、下载项目 2.2、功能介绍 三、打包工具&#xff08;nuitka&#xff09; 四、项目文件复制&#xff08;我全部合到一个文件里面了&#xff09; 五、结语 一、前言 看见b站的向军大叔用electron制作了一个桌面摄像头软件 但是&#x…

如何在jupyter notebook 中下载第三方库

在anconda 中找到&#xff1a; Anaconda Prompt 进入页面后的样式&#xff1a; 在黑色框中输入&#xff1a; 下载第三方库的命令 第三方库&#xff1a; 三种输入方式 标准保证正确 pip instsall 包名 -i 镜像源地址 pip install pip 是 Python 包管理工具&#xff0c;…

新项目,Linux上一键安装MySQL,Redis,Nacos,Minio

大家好&#xff0c;我是 jonssonyan 分享一个我的一个开源项目&#xff0c;这是一个在 Linux 平台上一键安装各种软件的脚本项目&#xff0c;脚本使用 Shell 语言编写&#xff0c;后续还会增加更多软件的一键安装&#xff0c;代码在 GitHub 上全部开源的&#xff0c;开源地址如…

【Python】进阶学习:pandas--如何根据指定条件筛选数据

【Python】进阶学习&#xff1a;pandas–如何根据指定条件筛选数据 &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程&#x1f448; 希望…

2024第二次培训:win11系统下使用nginx、JDK、mysql搭建基于vue2、java前后端分离的web应用运行环境

一.背景 公司安排了带徒弟的任务&#xff0c;给培训写点材料。前面分开介绍了mysql、jdk、nginx的安装&#xff0c;都只是零星的介绍&#xff0c;只能算零散的学习。学习了有什么用呢&#xff1f;能解决什么问题&#xff1f;能完成什么工作&#xff1f; 今天我们要用之前的几篇…

为什么要在业务系统中引入大宽表?

在高度系统化驱动的业务中&#xff0c;查看业务报表已经是一个很常见的需求了。在分工非常明确的大型企业里&#xff0c;往往有专门的数据分析团队 BI 或者数据开发团队&#xff0c;他们能够胜任此类需求&#xff08;但也未必是轻松的&#xff0c;或者说高效的&#xff09;。 …

Stable Diffusion 模型分享:AAM XL (Anime Mix)(动漫截屏风格 XL)

本文收录于《AI绘画从入门到精通》专栏&#xff0c;专栏总目录&#xff1a;点这里。 文章目录 模型介绍生成案例案例一案例二案例三案例四案例五案例六案例七案例八 下载地址 模型介绍 AAM XL (Anime Mix) 是一个动漫截屏风格的模型&#xff0c;是 AAM - AnyLoRA Anime Mix 模…

【yolov8部署实战】VS2019环境下使用C++和OpenCV环境部署yolo项目|含详细注释源码

一、前言 之前一阵子一直在做的就是怎么把yolo项目部署成c项目&#xff0c;因为项目需要嵌套进yolo模型跑算法。因为自己也是本科生小白一枚&#xff0c;基本上对这方面没有涉猎过&#xff0c;自己一个人从网上到处搜寻资料&#xff0c;写代码&#xff0c;调试&#xff0c;期间…

黑马JavaWeb开发跟学(三)Web前端开发Vue-Element

黑马JavaWeb开发跟学三.Web前端开发Vue-Element 1 Ajax1.1 Ajax介绍1.1.1 Ajax概述1.1.2 Ajax作用1.1.3 同步异步 1.2 原生Ajax1.3 Axios1.3.1 Axios的基本使用1.3.2 Axios快速入门1.3.3 请求方法的别名1.3.4 案例 2 前后台分离开发2.1 前后台分离开发介绍2.2 YAPI2.2.1 YAPI介…

【GPU驱动开发】-mesa简介

前言 不必害怕未知&#xff0c;无需恐惧犯错&#xff0c;做一个Creator&#xff01; 一、mesa介绍 Mesa 是一个开源的3D图形库&#xff0c;它实现了多种图形API&#xff0c;包括 OpenGL、Vulkan 和 OpenCL。Mesa 的目标是提供一个开源、跨平台的图形库&#xff0c;使得开发者…

ABAP - SALV教程08 列设置热点及绑定点击事件

实现思路&#xff1a;将列设置成热点&#xff0c;热点列是可点击的&#xff0c;再给SALV实例对象注册点击事件即可&#xff0c;一般作用于点击单号跳转到前台等功能 "设置热点方法METHODS:set_hotspot CHANGING co_alv TYPE REF TO cl_salv_table...."事件处理方法M…

合宙esp32-c3 进入深度睡眠无法唤醒解决一例

手贱&#xff0c;昨天收到了嘉立创最新的esp32 s3,想测试一下电流功耗&#xff0c;于是顺便测试了一下以前的合宙esp32 c3 无串口芯片的版本 打算对比一下c3和s3的功耗相差多少&#xff0c;结果把自己玩死了&#xff1a; void setup() {esp_deep_sleep_start();// esp_light_s…