C++从入门到精通——命名空间

news/2024/4/27 21:52:50/文章来源:https://blog.csdn.net/qq_74013365/article/details/137120854

命名空间

  • 前言
  • 一、命名空间
    • 引例
    • 什么是命名空间
  • 二、命名空间定义
    • 正常的命名空间定义
    • 嵌套的命名空间
    • 多个相同名称的命名空间
  • 三、命名空间使用
    • 加命名空间名称及作用域限定符
    • 使用`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 命名空间名称引用

直接引用NN会成为上述所说的第三查找标准

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++代码。


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

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

相关文章

Zookeeper的系统架构

先看一张图&#xff1a; ZooKeeper 的架构图中我们需要了解和掌握的主要有&#xff1a; 1&#xff1a; ZooKeeper分为服务器端&#xff08;Server&#xff09; 和客户端&#xff08;Client&#xff09;&#xff0c;客户端可以连接到整个ZooKeeper服务的任意服务器上&#xff…

Redis高级面试题-2024

说说你对Redis的理解 Redis是一个基于Key-Value存储结构的开源内存数据库&#xff0c;也是一种NoSQL数据库。 它支持多种数据类型&#xff0c;包括String、Map、Set、ZSet和List&#xff0c;以满足不同应用场景的需求。 Redis以内存存储和优化的数据结构为基础&#xff0c;提…

java反射应用:调用一个公共方法来间接调取其它各类方法

1.公共方法里用反射 2.通过反射调取进来的其它方法里&#xff0c;该方法想要调用另一个beanA来查询数据库&#xff0c;用Autowired 是不行的 因为beanA载入不了。这时需要利用上下文对象来获取beanA,来实现该方法里再查库的目的。 // / 方法4 import org.springframework.con…

Redis进阶(持久化、复制、集群、多线程、缓存)

Redis进阶 1.Redis持久化1.1 什么是Redis持久化&#xff1f;为什么需要持久化&#xff1f;1.2 Redis持久化方式——RDB(Redis DataBase)1.2.1 什么是RDB&#xff1f;1.2.2 备份文件位置1.2.3 触发RDB的方式1.2.3.1 自动触发1.2.3.2 手动触发1.2.3.3 其他触发方式 1.2.4 RDB优缺…

人工智能与大数据、云计算等其他技术的关联和区别是什么?

人工智能&#xff08;AI&#xff09;、大数据和云计算是当今科技领域的三大热门技术&#xff0c;它们之间存在密切的关联&#xff0c;但也有一些明显的区别。以下是它们之间的关联和区别&#xff1a; AI-321 | 专注于AI工具分享的网站 AI工具集 | 人工智能工具箱 | 全球顶尖AI…

hcia datacom课程学习(3):http与https、FTP

1.超文本传输协议&#xff1a;http与https &#xff08;1&#xff09;用来访问www万维网。 wwwhttp&#xff0b;html&#xff0b;URLweb &#xff08;2&#xff09;它们提供了一种发布和接受html界面的方法&#xff1a;当在网页输入URL后&#xff0c;从服务器获取html文件来…

leetcode每日一题 2642.设计可以求最短路径的图

题目详情 给你一个有 n 个节点的 有向带权 图&#xff0c;节点编号为 0 到 n - 1 。图中的初始边用数组 edges 表示&#xff0c;其中 edges[i] [fromi, toi, edgeCosti] 表示从 fromi 到 toi 有一条代价为 edgeCosti 的边。 请你实现一个 Graph 类&#xff1a; Graph(int n, i…

MySQL面试汇总(一)

MySQL 如何定位慢查询 如何优化慢查询 索引及其底层实现 索引是一个数据结构&#xff0c;可以帮助MySQL高效获取数据。 聚簇索引和非聚簇索引 覆盖索引 索引创建原则 联合索引

【matlab程序】海洋资料的获取与分析--AO/NAO

海洋资料的获取与分析 相关数据代码等资料已上传入群中 海洋资料下载和介绍 AO和NAO指数均取自美国气候预测中心&#xff08;Climate Prediction Center, CPC&#xff09;发布的月平均指数&#xff0c;时间跨度为1950-2022年。由于AO和NAO在冬季最强&#xff0c;因此本文选取…

基于51单片机一氧化碳(CO)浓度检测报警仿真LCD显示( proteus仿真+程序+设计报告+原理图+讲解视频)

基于51单片机一氧化碳(CO)浓度检测报警仿真LCD显示( proteus仿真程序设计报告原理图讲解视频&#xff09; 基于51单片机一氧化碳浓度检测报警仿真 1. 主要功能&#xff1a;2. 讲解视频&#xff1a;3. 仿真4. 程序代码5. 设计报告6. 原理图7. 设计资料内容清单&&下载链…

栅格地图路径规划:基于小龙虾优化算法(Crayfsh optimization algorithm,COA)的机器人路径规划(提供MATLAB代码)

一、机器人路径规划介绍 移动机器人&#xff08;Mobile robot&#xff0c;MR&#xff09;的路径规划是 移动机器人研究的重要分支之&#xff0c;是对其进行控制的基础。根据环境信息的已知程度不同&#xff0c;路径规划分为基于环境信息已知的全局路径规划和基于环境信息未知或…

深度学习(三)vscode加jupyter notebook插件使用

0.前言 哎呀&#xff0c;我本次的实验是在新电脑上使用的&#xff0c;之前的笔记本上的环境什么的我都是很久以前弄好了的&#xff0c;结果到了新电脑上我直接忘了是该怎么配的了&#xff0c;不过万幸&#xff0c;花了点时间&#xff0c;查查补补&#xff0c;现在总算是可以了。…

C# 读取二维数组集合输出到Word预设表格

目录 应用场景 设计约定 范例运行环境 配置Office DCOM 实现代码 组件库引入 核心代码 DataSet转二维数组 导出写入WORD表格 调用举例 小结 应用场景 存储或导出个人WORD版简历是招聘应用系统中的常用功能&#xff0c;我们通常会通过应用系统采集用户的个人简历信息…

赛氪网亮相中国人工智能产业发展联盟会议,共筑赛事生态新篇章

2024年3月14日至15日&#xff0c;备受瞩目的中国人工智能产业发展联盟&#xff08;AIIA&#xff09;第十一次全体会议在海南海口盛大召开。作为人工智能领域的重要交流与合作平台&#xff0c;此次会议吸引了300余位联盟成员单位代表齐聚一堂&#xff0c;共襄盛举。在这场人工智…

04. 【Android教程】Android 工程解析及使用

在上一章中已经搭建好了 Android 开发环境&#xff0c;本章我们将一起通过 Eclipse 创建我们的第一个 Android App。 1. 创建 Android 工程 首先打开 Eclipse&#xff0c;在菜单栏依次选择“New” -> “Android App Project”。如果是第一次创建&#xff0c;可能没有“Andr…

Redis项目实战

本文用用代码演示Redis实现分布式缓存、分布式锁、接口幂等性、接口防刷的功能。 课程地址&#xff1a;Redis实战系列-课程大纲_哔哩哔哩_bilibili 目录 一. 新建springBoot项目整合Redis 二. Redis实现分布式缓存 2.1 原理及好处 2.2 数据准备 2.3 Redis实现分布式缓存…

软件杯 深度学习 机器视觉 人脸识别系统 - opencv python

文章目录 0 前言1 机器学习-人脸识别过程人脸检测人脸对其人脸特征向量化人脸识别 2 深度学习-人脸识别过程人脸检测人脸识别Metric Larning 3 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 深度学习 机器视觉 人脸识别系统 该项目…

stm32之GPIO寄存器

文章目录 1 背景2 GPIO寄存器的类型2.1 端口配置寄存器2.2 设置/清除寄存器和位清除寄存器 3 总结 1 背景 C51单片机在进行数据的输入输出时&#xff0c;是直接操作与外部引脚关联的内部寄存器&#xff0c;例如&#xff0c;当设置P2_1为0时&#xff0c;就是将外部引脚的P21引脚…

Spark DAG

Spark DAG 什么是DAG DAG 是一组顶点和边的组合。顶点代表了 RDD&#xff0c; 边代表了对 RDD 的一系列操作。 DAG Scheduler 会根据 RDD 的 transformation 动作&#xff0c;将 DAG 分为不同的 stage&#xff0c;每个 stage 中分为多个 task&#xff0c;这些 task 可以并行运…

后端前行Vue之路(一):初识Vue

1.Vue是什么 Vue (读音 /vjuː/&#xff0c;类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是&#xff0c;Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层&#xff0c;不仅易于上手&#xff0c;还便于与第三方库或既有项目整合。另一方…