【C++掌中宝】深入解析C++命名空间:有效管理代码的利器
文章目录
- 前言
- 1. namespace 的价值
- 2. namespace 的定义
- 3. 命名空间的本质
- 4. 嵌套的命名空间
- 5. 命名空间的使用
- 6. using 指令
- 7. 补充
- 结语
前言
假设这样一种情况,当一个班上有两个名叫 Zara 的学生时,为了明确区分它们,我们在使用名字之外,不得不使用一些额外的信息,比如他们的家庭住址,或者他们父母的名字等等。
同样的情况也出现在 C++ 应用程序中。例如,您可能会写一个名为 xyz()
的函数,在另一个可用的库中也存在一个相同的函数 xyz()
。这样,编译器就无法判断您所使用的是哪一个 xyz()
函数。
我们举一个计算机系统中的例子,一个文件夹(目录)中可以包含多个文件夹,每个文件夹中不能有相同的文件名,但不同文件夹中的文件可以重名。
1. namespace 的价值
在C/C++中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染,namespace关键字的出现就是针对这种问题的。
c语言项目类似下面程序这样的命名冲突是普遍存在的问题,C++引入了命名空间这个概念,就是专门用于解决这种问题,它可作为附加信息来区分不同库中相同名称的函数、类、变量等。使用了命名空间即定义了上下文。本质上,命名空间就是定义了一个范围。
#include <stdio.h>
#include <stdlib.h>
int rand = 10;
int main()
{// 编译报错:error C2365: “rand”: 重定义;以前的定义是“函数”printf("%d\n", rand);return 0;
}
2. namespace 的定义
命名空间的定义使用关键字 namespace,后跟命名空间的名称,然后接⼀对{}即可,{}中即为命名空间的成员。命名空间中可以定义变量/函数/类型等。如下所示:
namespace namespace_name {// 代码声明
}
为了调用带有命名空间的函数或变量,需要在前面加上命名空间的名称,如下所示:
name::code; // code 可以是变量或函数
这里面的::
是作用域限定符。
让我们来看看命名空间如何为变量或函数等实体定义范围:
#include <iostream>
using namespace std;// 第一个命名空间
namespace first_space{void func(){cout << "Inside first_space" << endl;}
}
// 第二个命名空间
namespace second_space{void func(){cout << "Inside second_space" << endl;}
}
int main ()
{// 调用第一个命名空间中的函数first_space::func();// 调用第二个命名空间中的函数second_space::func(); return 0;
}
当上面的代码被编译和执行时,它会产生下列结果:
Inside first_space
Inside second_space
3. 命名空间的本质
- namespace本质是定义出一个域,这个域跟全局域各自独立,不同的域可以定义同名变量,所以下面的rand不在冲突了。
#include <stdio.h>
#include <stdlib.h>
// 1. 一般的命名空间定义
// xhh是命名空间的名字,一般开发中是用项目名字做命名空间名。
namespace xhh
{// 命名空间中可以定义变量/函数/类型int rand = 10;int Add(int left, int right){return left + right;}struct Node{struct Node* next;int val;};
}
int main()
{// 这⾥默认是访问的是全局的rand函数指针printf("%p\n", rand);// 这⾥指定xhh命名空间中的randprintf("%d\n", xhh::rand);return 0;
}
C++中域有函数局部域,全局域,命名空间域,类域;域影响的是编译时语法查找一个变量/函数/类型出处(声明或定义)的逻辑,所有有了域隔离,名字冲突就解决了。局部域和全局域除了会影响编译查找逻辑,还会影响变量的生命周期,命名空间域和类域不影响变量生命周期。
4. 嵌套的命名空间
namespace 只能定义在全局,当然还可以嵌套定义,示例如下。
//2. 命名空间可以嵌套
namespace bit
{namespace pig{int rand = 1;int Add(int left, int right){return left + right;}}namespace bird{int rand = 2;int Add(int left, int right){return (left + right) * 10;}}
}
int main()
{printf("%d\n", bit::pig::rand);printf("%d\n", bit::bird::rand);printf("%d\n", bit::pig::Add(1, 2));printf("%d\n", bit::bird::Add(1, 2));return 0;
}
5. 命名空间的使用
编译查找一个变量的声明/定义时,默认只会在局部或者全局查找,不会到命名空间里面去查找。所以下面程序会编译报错。
#include<stdio.h>
namespace N
{int a = 0;int b = 1;
}
int main()
{// 编译报错:error C2065: “a”: 未声明的标识符printf("%d\n", a);return 0;
}
所以声明了命名空间之后,如果在命名空间外部访问命名空间内部的成员,需要在成员名前面加上 命名空间::
,示例如下。
// 指定命名空间访问
int main()
{printf("%d\n", N::a);return 0;
}
6. using 指令
有没有什么比较方便的方法能让我们直接通过成员名访问命名空间内的成员呢?答案是肯定的。我们可以使用 using
指令。
using
指令有如下两种形式:
using 命名空间::成员名;
这条指令可以让我们省略某个成员名前的命名空间,直接通过成员名访问成员,相当于将这个成员导入了当前的作用域。
// using将命名空间中某个成员展开
using N::b;
int main()
{printf("%d\n", N::a);printf("%d\n", b);return 0;
}
using namespace 命名空间;
这条指令可以直接通过成员名访问命名空间中的任何成员,相当于将这个命名空间的所有成员导入了当前的作用域。
// 展开命名空间中全部成员
using namespce N;
int main()
{printf("%d\n", a);printf("%d\n", b);return 0;
}
因此,如果执行了 using namespace N;
,就会将 N
中的所有名字都会引入到全局命名空间当中。
📌注意
指定命名空间访问。项目中推荐这种方式。
using将命名空间中某个成员展开。项目中经常访问的不存在冲突的成员推荐这种方式。
展开命名空间中全部成员,由于这种方式会将此命名空间中的所有名字引入,因此如果声明了与其中重名的变量或函数,就可能会因为命名冲突而导致编译错误。所以说项目中不推荐,冲突风险很大,日常小练习程序为了方便推荐使用。
7. 补充
-
项目工程中多文件中定义的同名namespace会认为是一个namespace,不会冲突。
-
C++标准库都放在一个叫std(standard)的命名空间中。
结语
今天的分享到这里就结束啦!如果觉得文章还不错的话,可以三连支持一下。
也可以点点关注,避免以后找不到我哦!
Crossoads主页还有很多有趣的文章,欢迎小伙伴们前去点评,您的支持就是作者前进的动力!
相关文章:

【C++掌中宝】深入解析C++命名空间:有效管理代码的利器
文章目录 前言1. namespace 的价值2. namespace 的定义3. 命名空间的本质4. 嵌套的命名空间5. 命名空间的使用6. using 指令7. 补充结语 前言 假设这样一种情况,当一个班上有两个名叫 Zara 的学生时,为了明确区分它们,我们在使用名字之外&am…...

2024/9/21 leetcode 21.合并两个有序链表 2.两数相加
目录 21.合并两个有序链表 题目描述 题目链接 解题思路与代码 2.两数相加 题目描述 题目链接 解题思路与代码 --------------------------------------------------------------------------- 21.合并两个有序链表 题目描述 将两个升序链表合并为一个新的 升序 链表并返…...

Python学习的主要知识框架
Python的主要学习知识点非常广泛且深入,但我可以为您概括一些核心的学习领域,帮助您系统地掌握Python编程。以下是Python学习的主要知识框架: 1. Python基础语法 数据类型:整数、浮点数、字符串、布尔值、列表、元组、字典、集合…...

LLaMA-Factory 使用 alpaca 格式的数据集
LLaMA-Factory 使用 alpaca 格式的数据集 flyfish alpaca 格式最初与Stanford大学的一个研究项目相关联,该项目旨在通过少量高质量的数据来微调大型语言模型。它受到了Alpaca模型(一种基于LLaMA的指令跟随模型)的影响,该模型是在…...

【Mysql】Mysql数据库基础
1.❤️❤️前言~🥳🎉🎉🎉 Hello, Hello~ 亲爱的朋友们👋👋,这里是E绵绵呀✍️✍️。 如果你喜欢这篇文章,请别吝啬你的点赞❤️❤️和收藏📖📖。如果你对我的…...

一文彻底让你搞懂轨迹规划(总结)
机器人在运行中不可避免的会进行运动,那么就会产生出轨迹规划的概念。 轨迹规划的特点:用一定的函数形式表示控制量(位置,速度,加速度)的控制律,根据约束或最优目标,求取控制控制参…...

windows C++ 并行编程-异步消息块(二)
overwrite_buffer 类 concurrency::overwrite_buffer 类与 unbounded_buffer 类类似,只不过 overwrite_buffer 对象仅存储一条消息。 此外,当目标接收来自 overwrite_buffer 对象的消息时,不会从缓冲区中删除该消息。 因此,多个目…...

【软件基础知识】什么是 API,详细解读
想象一下,你正在使用智能手机上的天气应用。你打开应用,瞬间就能看到实时天气、未来预报,甚至是空气质量指数。但你有没有想过,这些数据是如何神奇地出现在你的屏幕上的?答案就在三个字母中:API。 API,全称Application Programming Interface(应用程序编程接口),是现代软件世…...

计算机四级-计算机网络
一、基础知识 1.对计算机网络发展具有重要影响的广域网是:ARPANET 随机争用型的介质访问控制方法起源于:ALOHANET 2.计算机网络发展阶段: A)第一阶段的主要成果是计算机技术与通信技术的结合 B)第二阶段的主要成果…...

【linux 获取时间】
linux 获取时间接口 我们在开发调试过程中,可能遇到一些和调用时序相关的问题,为了查看哪个步骤先调用,哪个步骤后调用,我们可以使用函数打印或者主动trace堆栈…但是有的时候我们需要排查2个接口调用的时间间隔,我们可…...

Dockerfile部署xxljob
使用Dockerfile部署xxljob 1. 背景 我们在使用定时任务调度时,通常会使用xxljob容器化部署xxljob,通常使用 docker pull xuxueli/xxl-job-admin:2.4.0 拉取镜像并启动容器。这种方式对于x86架构服务器来说,没有任何问题。但是在arm架构的服…...

Conda新建python虚拟环境问题
Conda新建python虚拟环境问题: 【问题1】 conda create --name yolov8 python3.10 -y Retrieving notices: …working… done Channels: defaults Platform: win-64 Collecting package metadata (repodata.json): failed UnavailableInvalidChannel: HTTP 404 NO…...

这几个优秀的工具网站真心值得推荐——搜嗖工具箱
即时工具 https://www.67tool.com/ 这是一个专注提升效率的办公工具网站;这也是一个拥有260多款自研在线工具和200多个客户端离线工具的服务网站;这还是一个可以满足包括视频处理、音频处理、图片处理、文档处理、文档转换、办公辅助、图表生成、文本工…...

ESP32开发 -- VSCODE+PlatformIO环境安装
参看官网安装:PlatformIO IDE for VSCode 一、安装PlatformIO IDE 参看:日常生活小技巧 – Visual Studio Code 简单使用 扩展中搜索platformIO IDE 当安装完提示重启之后。 打开一个要创建新工程的文件夹: 点击 Create New Project&…...

MySQL--导入SQL文件(命令行导入)
MySQL--导入SQL文件 一、前言二、导入SQL文件 一、前言 用可视化编辑工具编写,并且在控制台输入命令行在MySQL中导入SQL文件。 在导入SQL文件之前查看了目前存在的数据库 **目标:**在可视化编辑工具(这里以word文档为例)中编写SQL语句&…...

【C#基础】函数传参大总结
目录 前言参数是值类型的情况1. 按值传递(Pass by Value)2. 按引用传递(Pass by Reference)使用 ref使用 in 3. 输出参数传递(Output Parameters)参数修饰符对比小结 参数是引用类型的情况1. 按值传递类对象…...

初学51单片机之IO口上下拉电阻相关
本案本来是描述一下I2C总线的,在此之前推荐一下B站一个UP关于时序图的讲解 I2C入门第一节-I2C的基本工作原理_哔哩哔哩_bilibili 不过在描述I2C前先简单的探讨下51单片机IO口下拉电阻的基本情况,事实上这个问题困扰笔者很长时间了,这次也是一…...

Resnet50网络——口腔癌病变识别
一 数据准备 1.导入数据 import matplotlib.pyplot as plt import tensorflow as tf import warnings as w w.filterwarnings(ignore) # 支持中文 plt.rcParams[font.sans-serif] [SimHei] # 用来正常显示中文标签 plt.rcParams[axes.unicode_minus] False # 用来正常显示负…...

Python 中自动打开网页并点击[自动化脚本],Selenium
要在 Python 中自动打开网页并点击第一个 <a> 标签,你需要使用 Selenium,它可以控制浏览器并执行像点击这样的操作。requests 和 BeautifulSoup 只能获取并解析网页内容,但不能进行网页交互操作。 步骤: 安装 Selenium安装…...

Spring Boot-自动配置问题
**### Spring Boot自动配置问题探讨 Spring Boot 是当前 Java 后端开发中非常流行的框架,其核心特性之一便是“自动配置”(Auto-Configuration)。自动配置大大简化了应用开发过程,开发者不需要编写大量的 XML 配置或是繁琐的 Jav…...

CS61B学习 part1
本人选择了2018spring的课程,因为他免费提供了评分机器,后来得知2021也开放了,决定把其中的Lab尝试一番,听说gitlab就近好评,相当有实力,并借此学习Java的基本知识,请根据pku的cswiki做好评分机…...

我Github的问题解决了!
看的这篇,解决使用git时遇到Failed to connect to github.com port 443 after 21090 ms: Couldn‘t connect to server_git couldnt connect to server-CSDN博客 之前想推送的能推送了,拉取的也能取了。 一、如果是在挂着梯子的情况下拉取或者推送代码…...

Pytorch构建神经网络多元线性回归模型
1.模型线性方程y W ∗ X b from torch import nn import torch#手动设置的W参数(待模型学习),这里设置为12个,自己随意设置weight_settorch.tensor([[1.5,2.38,4.22,6.5,7.2,3.21,4.44,6.55,2.48,-1.75,-3.26,4.78]])#手动设置…...

如何基于Flink CDC与OceanBase构建实时数仓,实现简化链路,高效排查
本文作者:阿里云Flink SQL负责人,伍翀,Apache Flink PMC Member & Committer 众多数据领域的专业人士都很熟悉Apache Flink,它作为流式计算引擎,流批一体,其核心在于其强大的分布式流数据处理能力&…...

ActiveMQ、RabbitMQ 和 Kafka 在 Spring Boot 中的实战
在现代的微服务架构和分布式系统中,消息队列 是一种常见的异步通信工具。消息队列允许应用程序之间通过 生产者-消费者模型 进行松耦合、异步交互。在 Spring Boot 中,我们可以通过简单的配置来集成不同的消息队列系统,包括 ActiveMQ、Rabbit…...

火语言RPA流程组件介绍--获取关联元素
🚩【组件功能】:获取指定元素的父元素、子元素、相邻元素等关联信息 配置预览 配置说明 目标元素 支持T或# 默认FLOW输入项 通过自动捕获工具捕获(选择元素工具使用方法)或手动填写网页元素的css,xpath,指定对应网页元素作为操作目标 关联…...

【2024研赛】【华为杯E题】2024 年研究生数学建模比赛思路、代码、论文助攻
思路将在名片下群聊分享 高速公路应急车道紧急启用模型 高速公路拥堵现象的原因众多,除了交通事故外,最典型的就是部分路段出现瓶颈现象,主要原因是车辆汇聚,而拥堵后又容易蔓延。高速公路一些特定的路段容易形成堵点࿰…...

Linux——K8s集群部署过程
1、环境准备 (1)配置好网络ip和主机名 control: node1: node2: 配置ip 主机名的过程省略 配置一个简单的基于hosts文件的名称解析 [rootnode1 ~]# vim /etc/hosts // 文件中新增以下三行 192.168.110.10 control 192.168.110.11 node1 1…...

二.Unity中使用虚拟摇杆来控制角色移动
上一篇中我们完成了不借助第三方插件实现手游的虚拟摇杆,现在借助这个虚拟摇杆来实现控制角色的移动。 虚拟摇杆实际上就给角色输出方向,类似于键盘的WSAD,也是一个二维坐标,也就是(-1,1)的范围,将摇杆的方向进行归一化…...

基于SpringBoot的旅游管理系统
系统展示 用户前台界面 管理员后台界面 系统背景 近年来,随着社会经济的快速发展和人民生活水平的显著提高,旅游已成为人们休闲娱乐、增长见识的重要方式。国家积极倡导“全民旅游”,鼓励民众利用节假日外出旅行,探索各地自然与人…...