【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类定义stud1
    stud1.get_data();
    cout <<ns1:: fun(5, 3) << endl;//调用命名空间ns1中的fun函数
    ns2::Student stud2(102, "Li", 'f');//用命名空间ns2中的Student类定义stud2
    stud2.get_data();
    cout << ns2::fun(5, 3) << endl;//调用命名空间ns2中的fun函数
    return 0;
}

运行结果如下:

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ChatGPT科研与AI绘图及论文高效写作教程

原文链接&#xff1a;ChatGPT科研与AI绘图及论文高效写作教程 2023年随着OpenAI开发者大会的召开&#xff0c;最重磅更新当属GPTs&#xff0c;多模态API&#xff0c;未来自定义专属的GPT。微软创始人比尔盖茨称ChatGPT的出现有着重大历史意义&#xff0c;不亚于互联网和个人电…

反序列化逃逸 [安洵杯 2019]easy_serialize_php1

打开题目 题目源码&#xff1a; <?php$function $_GET[f];function filter($img){$filter_arr array(php,flag,php5,php4,fl1g);$filter /.implode(|,$filter_arr)./i;return preg_replace($filter,,$img); }if($_SESSION){unset($_SESSION); }$_SESSION["user&qu…

python 基础知识点(蓝桥杯python科目个人复习计划56)

今日复习内容&#xff1a;做题 例题1&#xff1a;最小的或运算 问题描述&#xff1a;给定整数a,b&#xff0c;求最小的整数x&#xff0c;满足a|x b|x&#xff0c;其中|表示或运算。 输入格式&#xff1a; 第一行包括两个正整数a&#xff0c;b&#xff1b; 输出格式&#…

Java项目layui分页中文乱码

【问题描述】这部分没改之前中文乱码。 【解决办法】在layui.js或者layui.all.js文件中替换共、页、条转换成Unicode码格式。 字符Unicode共&#x5171页&#x9875条&#x6761【完美解决】改完之后重新运行项目&#xff0c;浏览器F12缓存清除就好了&#xff0c;右键

递归回溯剪枝-括号生成

LCR 085. 括号生成 - 力扣&#xff08;LeetCode&#xff09; 一. 根据题意&#xff0c;分析出符合要求的括号组合需要满足以下两个条件&#xff1a; 1. 左括号数或者右括号数都不能超过 n&#xff1b; 2. 从最左侧开始的每一个子集&#xff0c;不可以出现右括号数大于左括号数&…

力扣1892 页面推荐Ⅱ

力扣1892&#xff0c;页面推荐Ⅱ&#xff0c;为一个社交媒体网站实施一个页面推荐系统。如果页面被user_id的 至少一个朋友喜欢 &#xff0c;而 不被user_id喜欢 &#xff0c;你的系统将 推荐 一个页面到user_id。 目录 题目描述 解题思路 完整代码 优化 题目描述 表&…

有道QAnything背后的故事---关于RAG的一点经验分享

近日&#xff0c;我们开源了有道自研的RAG&#xff08;Retrieval Augmented Generation) 引擎QAnything。该引擎允许用户上传PDF、图片、Word、Excel、PowerPoint等多种格式的文档&#xff0c;并实现类似于ChatGPT的互动问答功能&#xff0c;其中每个答案都能精确追溯到相应的文…

Kaggle竞赛之Titanic存活预测2

提高代码规范性&#xff0c;基于上一个 baseline 的提高 import pandas as pd from sklearn.preprocessing import LabelBinarizer from sklearn.preprocessing import StandardScaler from sklearn.model_selection import train_test_split#数据划分方法 from sklearn.ensem…

FL Studio选购指南:新手小白应该选择哪个版本FL Studio?

很多打算入手正版FL Studio的新手朋友都会纠结一个问题&#xff1a;哪个版本的FL Studio更适合我&#xff0c;到底应该入手哪一款FL Studio&#xff1f;本文会介绍每个版本之间的差异点&#xff0c;并带大家选择适合自己的FL Sudio版本。 FL Studio全版本 在选购前有一些小知识…

动态代理如何获取动态生成的代理类的class文件

JDK动态代理 在使用JDK动态代理&#xff0c;即reflect包下的Proxy类的newProxyInstance方法时&#xff0c;会在运行时&#xff0c;根据传进来的接口类型动态生成class字节码文件。这个字节码文件是在内存中动态获取的&#xff0c;程序结束就没有了&#xff0c;如何动态获取呢。…

创新之巅 健康之选 森歌集成灶智能水洗新揭秘

2024年2月27日&#xff0c;一场引领智能厨电风潮的盛会在杭州隆重召开。森歌集成灶以“勠力同心 共生共歌”为主题&#xff0c;成功举办了2024森歌智能厨电优秀经销商峰会。此次峰会上&#xff0c;森歌集成灶发布了令人瞩目的奥运冠军同款智能厨电新品——森歌鲸洗小灶Z60&…

paper-ai :搜索真实文献并生成引用真实文献的AI论文

paper-ai &#xff1a;搜索真实文献并生成引用真实文献的AI论文。 项目简介 使用真实文献最快速完成论文的方法 利用人工智能撰写论文 人工智能书写功能&#xff1a;点击 "AI 写作 "进行正常对话互动。人工智能将根据您的输入提供写作建议或回答问题。 寻找文献功能…

相纸尺寸和相纸分类解释

相纸分类 高光 高光相纸俗称光面相纸&#xff0c;适用一般的证件用照和生活照片&#xff0c;表面平滑光亮。 绒面 绒面相纸(也称哑光相纸或哑光相纸)&#xff0c;因为绒面革相纸的表面粗糙&#xff0c;所以绒面相纸的质地很好&#xff0c;表面有哑光感&#xff0c;没有反光…

ELK学习

ELK 一、ELK介绍 &#x1f604; “ELK”是三个开源项目的首字母缩写&#xff0c;这三个项目分别是&#xff1a;Elasticsearch、Logstash 和 Kibana。Elasticsearch 是一个搜索和分析引擎。Logstash 是服务器端数据处理管道&#xff0c;能够同时从多个来源采集数据&#xff0…

测试:腾讯云4核8G服务器支持多少人在线访问?

腾讯云4核8G服务器支持多少人在线访问&#xff1f;支持25人同时访问。实际上程序效率不同支持人数在线人数不同&#xff0c;公网带宽也是影响4核8G服务器并发数的一大因素&#xff0c;假设公网带宽太小&#xff0c;流量直接卡在入口&#xff0c;4核8G配置的CPU内存也会造成计算…

Heimdallr - 被动嗅探浏览器插件

Heimdallr - 被动嗅探浏览器插件 Heimdallr是一款致力于被动嗅探浏览器流量&#xff0c;提示高危资产指纹和蜜罐特征&#xff0c;并进行拦截告警的谷歌插件&#xff0c;还可以用于对浏览器特征追踪&#xff08;evercookie、webRTC、Canvas画布等&#xff09;的对抗。 项目由深…

《汇编语言》- 读书笔记 - 第15章-外中断

《汇编语言》- 读书笔记 - 第15章-外中断 15.1 接口芯片和端口15.2 外中断信息1. 可屏蔽中断&#xff08;Maskable Interrupt&#xff09;2. 不可屏蔽中断&#xff08;Non-Maskable Interrupt&#xff09;设计思想 15.3 PC 机键盘的处理过程1. 键盘输入2. 引发 9 号中断3. 执行…

在您的下一个项目中选择 Golang 和 Node.js 之间的抉择

作为一名软件开发者&#xff0c;我总是在寻找构建应用程序的最快、最高效的工具。在速度和处理复杂任务方面&#xff0c;我认为 Golang 和 Node.js 是顶尖技术。两者在性能方面都享有极高的声誉。但哪一个更快——Golang 还是 Node&#xff1f;我决定深入一些硬核基准测试&…

Java+SpringBoot+Vue:志愿服务的数字化之旅

✍✍计算机毕业编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java、…

LeetCode 刷题 [C++] 第226题.翻转二叉树

题目描述 给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 题目分析 深度优先搜索&#xff08;DFS&#xff09;- 递归方式 对于二叉树的镜像问题&#xff0c;很容易想到的就是使用递归来解决&#xff0c;自底向上依次翻转每一个节点…