C++_命名空间(namespace)

        

目录

1、namespace的重要性

2、 namespace的定义及作用

2.1 作用域限定符

 3、命名空间域与全局域的关系

4、命名空间的嵌套

 5、展开命名空间的方法

5.1 特定展开

5.1 部分展开

5.2 全部展开

结语:


前言:

        C++作为c语言的“升级版”,其在语法上相对于c语言有了诸多升级、优化,比如在C++中有一个全新的概念:命名空间(namespace)。在使用C++时,该语法很好的解决了对标识符命名重名的问题。

1、namespace的重要性

        在使用c语言写代码时,常常会遇到标识符命名重名的问题。比如我们自己写了一个函数,该函数名可能与库函数中的某个函数发生重名,或者与他人一起写项目时,也存在与他人代码中的标识符同名的现象,然而以上情况的解决方法只有对标识符进行改名。

        举例说明:

#include <stdio.h>
#include <time.h>
int time = 12;int main()
{printf("%d\n", time);return 0;
}
//程序编译时会报错,原因是预处理阶段会展开全部的头文件(.h文件)
//被展开头文件里面的内容是具有“全局性的”,即全局都能使用里面的内容
//然而time.h的文件中存在一个名为time的函数
//在编译阶段,编译器会发现全局中有两个time的名称,并且报错

        因此针对重定义、重命名的这类问题,C++就提出了一个新的概念namespace。

2、 namespace的定义及作用

        namespace又称命名空间,他是一块独立于全局范围内的区域,在namespace区域中定义各种标识符的名称和全局中是分割开的,换句话说就是对命名空间内的标识符名称进行本地化管理,这样就不会与全局作用域中的同名标识符起冲突了。

        比如,创建两个头文件first.h和second.h,并且把这两个头文件都包含到主函数文件main.cpp中:

//first.h文件:
#pragma once
int a = 10;//second.h文件:
#pragma once
int a = 101;//main.cpp文件:
//包含上述两个.h文件
#include"first.h"
#include"second.h"
#include<stdio.h>int main()
{printf("%d ",a);//a重定义了return 0;
}//会报错:a重定义

        上述代码若运行,则会发生编译报错,原因就是再展开这两个头文件后,会出现两个a多重定义的报错。这时候可以将其中一个头文件的变量a换另一个名称,或者main.cpp中只包含其中一个头文件。但是如果这两个文件都要包含而且也不想对变量a的名称进行更改,那么只能用namespace将两个头文件下的变量a存到命名空间内。

2.1 作用域限定符

        使用namespace进行对上述代码的优化:

//first.h文件:
#pragma once
namespace first//namespace用法:namespace+自定义名称
{int a = 10;}//second.h文件:
#pragma once
namespace second
{int a = 101;}//main.cpp文件:
//包含上述两个.h文件
#include"first.h"
#include"second.h"
#include<stdio.h>int main()
{printf("%d ", second::a);//::表示作用域限定符,左边跟作用域名称return 0;
}//会报错:a重定义

        上述代码则将两个头文件下的变量a都放在了两块不一样的命名空间内,这样一来他们的名称就不会互相干涉了,只不过在使用变量a的时候要多一个步骤:使用作用域限定符去特指的命名空间查找。因为编译器也不知道程序员需要用哪个a,所以程序员需要在使用的a的左边加上“::”符号,并且在“::”符号的左边加上命名空间的名称,这样就可以精确的使用某个命名空间里的内容了,也称展开命名空间。

        上述代码运行结果:

 3、命名空间域与全局域的关系

        如果上文中的代码没有对a使用“second::”,会出现什么样的后果呢?

        可以发现编译器显示找不到变量a了,因为编译器查找的顺序是先找局部、再找全局,并不会自动的去命名空间内查找,所以全局域和命名空间域是分开的两个区域。因此在上述代码中,当头文件里的变量a被存放在命名空间中,可以理解为该变量从全局域被移动至命名空间域。

        关系图:

        比如全局域和局部域都有一个名为a的变量,如果编译器在局部域中就找到了a,则编译器会直接调用该a的值,并且也不会去全局域中查找,用上述代码进行变形当作例子:

#include"first.h"
#include"second.h"
#include<stdio.h>int a = 1021;//全局变量int main()
{int a = 22;//局部变量printf("%d ", a);return 0;
}

         运行结果:

        可以看到编译器直接选用了局部变量a作为打印结果。并且我们新加了全局变量int a=1021,编译器也没有报重命名的错误,说明全局域和命名空间域是分开的的两个区域,在全局域中定义了一个a,则命名空间域也能使用a的名称。

4、命名空间的嵌套

         命名空间的嵌套就是在该空间内在创建一个命名空间,一般是防止最外层命名空间的名称与别的空间同名,写法如下:

//first.h
#pragma once
namespace first
{namespace A{int a = 10;}
}//second.h
#pragma once
namespace first//假设两个头文件下的第一层空间重名
{namespace B//则需要第二层空间来区别a变量{int a = 101;}
}//main.cpp
#include"first.h"
#include"second.h"
#include<stdio.h>int a = 1021;int main()
{printf("%d\n", first::A::a);printf("%d\n", first::B::a);return 0;
}

        运行结果:

 5、展开命名空间的方法

        展开命名空间就是从命名空间内读取内容,上文提到的作用域限定符就是其中的一个办法,但是如果读取大量的内容就会很麻烦,因为只要是每一次读取都要加上作用域限定符,会很繁琐。因此另两种方法是部分展开和全部展开。

5.1 特定展开

        特定展开就是上文的展开方式,既:空间名称::变量名称。值得一提的是,使用特定展开时,编译器不会去局部和全局找,而是直接到命名空间内找,因此就算全局也有与该变量一模一样的名称,也不会报错,而且编译器还是会调用命名空间内的变量。

        特定展开代码如下:

//first.h
#pragma once
namespace first
{int a = 10;
}//second.h
#pragma once
namespace second
{int a = 101;
}#include"first.h"
#include"second.h"
#include<stdio.h>
int a = 1021;int main()
{printf("%d\n", first::a);//编译器会调用first文件中的a,而不是调用全局a=1021的areturn 0;
}

         运行结果:

5.1 部分展开

        在全局处使用using+空间名称::变量名称。部分展开与特定展开就不一样了,部分展开是把要调用的变量移动到全局域中,然后编译器在全局域中找到该变量,并不是让编译器指定到该空间去找,因此要保证全局中不能出现与该变量一样的名称,不然会报错。

        部分展开逻辑图如下:

        具体代码如下:

//first.h
#pragma once
namespace first
{int a = 10;
}//second.h
#pragma once
namespace second
{int a = 101;
}//main.cpp
#include"first.h"
#include"second.h"
#include<stdio.h>
using first::a;//展开first空间并且只调用a
//int a = 1021;//注意这时候first.h里的变量a属于全局变量了,不能再定义额外名称的a的变量int main()
{printf("%d\n", a);printf("%d\n", a);return 0;
}

        运行结果:

         在全局处加上了using first::a,之后所有需要调用a变量的代码前面都不需要再加作用域限定符了。但是仅仅限于变量a不用加限定符,如果要调用first空间内其他的变量还是要加作用域限定符的,因此又引出一个新的概念:全部展开,全部展开某个命名空间,则后续的代码可以不加限定符直接调用该空间内的所有内容。

5.2 全部展开

        在全局处加上using+namespace+要展开空间的名称,既可对该空间进行全部展开。全局展开也同部分展开逻辑一样,全局展开相当于把该空间里的所有内容都移到全局域中,因此全局域中不能出现与该空间内有标识符名称相同的情况。

        全部展开代码如下:

//first.h
#pragma once
namespace first
{int a = 10;int b = 123;int c = 456;
}//second.h
#pragma once
namespace second
{int a = 101;
}//main.cpp
#include"first.h"
#include"second.h"
#include<stdio.h>
using namespace first;
//int a = 1021;int main()
{printf("%d\n", a);printf("%d\n", b);printf("%d\n", c);return 0;
}

        运行结果:

        从结果来看,当全部展开first空间后,可以随意使用该空间的内容而且无需添加任何条件。 

结语:

        以上就是关于C++中命名空间的介绍,对于命名空间的全部展开其实在一般的情况下是不推荐的,因为全部展开意味着空间内的所有内容都变成了全局的,很容易发生重名,也就失去了命名空间防止重名的意义。

        最后希望本文可以给你带来更多的收获,如果本文对你起到了帮助,希望可以动动小指头帮忙点赞👍+关注😎+收藏👌!如果有遗漏或者有误的地方欢迎大家在评论区补充~!!谢谢大家!!( ̄︶ ̄)↗ 

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

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

相关文章

快速排序的新用法

普通快排 简介 快速排序是一种高效的排序算法&#xff0c;利用分治的思想进行排序。它的基本原理是在待排序的n个数据中任取一个数据为分区标准&#xff0c;把所有小于该排序码的数据移到左边&#xff0c;把所有大于该排序码的数据移到右边&#xff0c;中间放所选记录&#x…

Spring 之 @Cacheable 缓存使用教程

1、Cacheable 指定使用缓存 定义个 Controller &#xff0c;在方法上加上注解 Cacheable&#xff0c;配置要使用哪些缓存&#xff0c;比如 myMapCache 表示一级缓存是 Map&#xff0c;myRedisCache 表示二级缓存是 Redis。并配置缓存 key。 key 由 SPEL 表达式组成&#xff0c…

异常检测 | MATLAB实现BiLSTM(双向长短期记忆神经网络)数据异常检测

异常检测 | MATLAB实现BiLSTM(双向长短期记忆神经网络)数据异常检测 目录 异常检测 | MATLAB实现BiLSTM(双向长短期记忆神经网络)数据异常检测效果一览基本介绍模型准备模型设计参考资料效果一览 基本介绍 训练一个双向 LSTM 自动编码器来检测机器是否正常工作。 自动编码器接受…

CleanMyMac X2024最新版本软件实用性测评

信大多数MAC用户都较为了解&#xff0c;Mac虽然有着许多亮点的性能&#xff0c;但是让用户叫苦不迭的还其硬盘空间小的特色&#xff0c;至于很多人因为文件堆积以及软件缓存等&#xff0c;造成系统空间内存不够使用的情况。于是清理工具就成为了大多数MAC用户使用频率较高的实用…

二十一章网络通信

计算机网络实现了多台计算机间的互联&#xff0c;使得它们彼此之间能够进行数据交流。网络应用程序就是在已连接的不同计算机上运行的程序&#xff0c;这些程序借助于网络协议&#xff0c;相互之间可以交换数据。编写网络应用程序前&#xff0c;首先必须明确所要使用的网络协议…

数据采集工具的大全【都是免费值得收藏】

数据是推动业务成功的关键之一。为了获取准确、全面的信息&#xff0c;数据采集成为了许多企业和个人的必备工作。本文将专注于数据采集工具&#xff0c;探讨其在全网和指定网站采集方面的优势&#xff0c;为大家提供对比分析&#xff0c;以帮助大家找到最适合的数据采集利器。…

算法复习——6种排序方法的简单回顾

算法复习——6种排序方法的简单回顾 常见排序方法&#xff1a;冒泡排序、选择排序、插入排序、堆排序、归并排序、快速排序的简单回顾 冒泡排序 重复“从序列右边开始比较相邻两个数字的大小,再根据结果交换两个数字的位置” 在冒泡排序中&#xff0c;第 1 轮需要比较 n - 1…

Tair(1):Tair介绍

1 介绍 ​ 在Tair出现之前的很长一段时间里&#xff0c;像redis、memcache这些知名NoSql数据库是不支持分布式的&#xff0c;在这样的背景下&#xff0c;由淘宝网自主开发并在2010.6开源的一个高性能、高扩展、高可靠分布式缓存&#xff0c;类似map的key/value结构&#xff0c…

使用单例模式+观察者模式实现参数配置实时更新

使用vector存储观察者列表 #include <iostream> #include <vector> #include <functional> #include <algorithm>// 配置参数结构体 struct MyConfigStruct {int parameter1;std::string parameter2; };class Config { public:using Observer std::f…

hive 命令行中使用 replace 和nvl2 函数报错

1.有时候在命令行的情况下使用 replace 函数时会报错 这个时候可以使用 translate 代替 2.有时候使用 nvl2() 函数的时候会报错 这个时候可以用 case when 来代替

【Spring 源码】 深入理解 Bean 定义之 BeanDefinition

&#x1f680; 作者主页&#xff1a; 有来技术 &#x1f525; 开源项目&#xff1a; youlai-mall &#x1f343; vue3-element-admin &#x1f343; youlai-boot &#x1f33a; 仓库主页&#xff1a; Gitee &#x1f4ab; Github &#x1f4ab; GitCode &#x1f496; 欢迎点赞…

两数之和问题

更好的阅读体验请点击 两数之和。 题目&#xff1a;两数之和 ​ 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 ​ 你可以假设每种输入只会对应一个答案。但是&#xff…

MetricBeat监控Redis

目录 一、安装部署 二、开启Redis监控模块 三、编辑Redis配置文件 四、启动Metricbeat 五、查看监控图表 一、安装部署 metriceat的安装部署参考章节&#xff1a; 监控组件>Metricbeat安装使用&#xff0c;这里不再赘述。 二、开启Redis监控模块 进入metricbeat安装目录…

【每日一题】出租车的最大盈利

文章目录 Tag题目来源解题思路方法一&#xff1a;递归方法二&#xff1a;递归记录数组记忆化搜索方法三&#xff1a;动态规划&#xff08;递推&#xff09; 写在最后 Tag 【递归】【记忆化搜索】【动态规划】【数组】【2023-12-08】 题目来源 2008. 出租车的最大盈利 解题思路…

【EI会议征稿中】2024年第四届人工智能、自动化与高性能计算国际会议(AIAHPC 2024)

2024年第四届人工智能、自动化与高性能计算国际会议&#xff08;AIAHPC 2024&#xff09; 2024 4th International Conference on Artificial Intelligence, Automation and High Performance Computing 2024第四届人工智能、自动化与高性能计算国际会议(AIAHPC 2024)将于20…

蓝桥杯从零开始备战(Python组)---基础知识篇

第一次尝试报名蓝桥杯的Python组&#xff0c;好好备战&#xff0c;希望省赛可以拿奖&#xff01;目前是整理了一些Python的常用函数和常用内置库&#xff0c;后面可能会开始刷题&#xff0c;如果有比较需要记住的知识点&#xff0c;会再写一篇刷题篇 一、输入输出 1.输入字符…

游戏被攻击怎么办

随着科技的进步和互联网的普及&#xff0c;游戏行业也正在经历前所未有的变革。玩家们不再满足于传统的线下游戏&#xff0c;而是转向了线上游戏。然而&#xff0c;随着游戏的线上化&#xff0c;游戏安全问题也日益凸显。游戏受到攻击是游戏开发者永远的痛点&#xff0c;谈“D“…

HomeAssistant添加HACS插件并实现公网控制米家,HomeKit等智能家居

HomeAssistant添加HACS插件并实现公网控制米家&#xff0c;HomeKit等智能家居 文章目录 HomeAssistant添加HACS插件并实现公网控制米家&#xff0c;HomeKit等智能家居基本条件一、下载HACS源码二、添加HACS集成三、绑定米家设备 ​ 上文介绍了如何实现群晖Docker部署HomeAssist…

【嵌入式开发 Linux 常用命令系列 4.1 -- git push 远程分支与本地分支查看】

文章目录 概述git push 语法步骤1&#xff1a;git 远程主机名查看步骤2&#xff1a;git 远程分支名查看步骤3&#xff1a;git 本地分支名查看示例演示 概述 在日常工作中&#xff0c;将代码 git clone 本地之后&#xff0c;或者使用repo init && repo sync 之后不知道…

SQLserver截取字符串

当我们存的数据是json的时候可以全部取出在模糊查询但是有多个重复数据的时候就没办法准确的模糊出来这个时候我们就需要用的字符串截取 --创建函数create FUNCTION [dbo].[Fmax] (str varchar(50),start VARCHAR(50),length VARCHAR(50)) RETURNS varchar(max) AS BEGINDEC…