C++——命名空间(namespace)

news2024/11/17 0:05:11

目录

1. C语言命名冲突

2. 命名空间定义

3. 命名空间使用

  • 可能大家在看别人写的C++代码中,在一开始会包这个头文件:#include<iostream>

这个头文件等价于我们在C语言学习到的#include<stdio.h>,它是用来跟我们的控制台输入和输出的,这里简要提下,后续详谈。

  • 除了上面这个头文件,还有这样一行代码:using namespace std;

namespace就是我们要接触C++的第一个关键字,它就是命名空间。

在C/C++中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染,namespace关键字的出现就是针对这种问题的。

1. C语言命名冲突

 在正式引入namespace前,再来回顾下C语言的命名冲突问题:

#include<stdio.h>
//命名冲突
int rand = 0;
int main()
{
	printf("%d", rand);
	return 0;
}

如上的代码中,头文件我们只用了intclude<stdio.h>,暂无其它。我们定义了全局变量rand,并且代码可以正常编译没有任何错误。

但是要知道C语言存在一个库函数正是rand,但是要包上头文件#include<stdlib.h>,包上了这个头文件,再运行试试:

这里很明显发生命名冲突了,我们定义的全局变量rand和库里的rand函数冲突

想要解决此问题也非常简单,可能有人会说我修改变量名就可以了,确实可以,但并不是长久之计,如若我在不知情的状态下使用该变量超过100次,难道你要一个一个修改吗,这就充分体现了C语言的命名冲突。

在C++中,引入的命名空间namespace就很好解决了C语言的命名冲突问题。

2. 命名空间定义

定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接一对{ }即可,{}中即为命名空间的成员。

如下:

 同一个作用域不能出现两个相同变量,此时的rand被关在n1的命名空间域里了,跟其它东西进行了隔离。所以在stdlib.h头文件展开时并不会发生命名冲突。此时rand的打印均是库函数里rand的地址,rand就是一个函数指针,打印的就是地址。

再比如:

此段代码更充分的体现了加上命名空间,不仅可以避免命名冲突,而且还告诉我们,此时再访问变量m、c、f,均是在全局域里访问的,而xzy这个命名空间域里的变量与全局域建立了一道围墙,互不干扰。不过这里c和m依旧是全局变量,命名空间不影响生命周期

命名空间有三大特性:

  • 1、命名空间可以定义变量,函数,类型
//1. 普通的命名空间
namespace N1 // N1为命名空间的名称
{
	// 命名空间中的内容,既可以定义变量,也可以定义函数,也可以定义类型
	int a; //变量
	int Add(int left, int right) //函数
	{
		return left + right;
	}
    struct ListNode //类型
    {
        int val;
        struct ListNode* next;
    }
 
}
  • 2、命名空间可以嵌套
//2. 命名空间可以嵌套
namespace N2
{
	int a;
	int b;
	int Add(int left, int right)
	{
		return left + right;
	}
	namespace N3
	{
		int c;
		int d;
		int Sub(int left, int right)
		{
			return left - right;
		}
	}
}
  • 3、同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中
//3. 同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中。
namespace N1
{
	int Mul(int left, int right)
	{
		return left * right;
	}
}

3. 命名空间使用

我们都清楚在C语言中,存在局部优先规则,如下:

int a = 0; //全局域
int main()
{
	int a = 1; //局部域
	printf("%d\n", a); // 1 局部优先
	return 0;
}

我们都清楚这里的结果是1,但是如若我非要打印全局域里的a呢?

这里引出域作用限定符 :: ),效果如下:

加上了( :: ) ,此时访问的a,就是全局域,这里是全局域的原因是“ ::”的前面是空白,如若是空白,那么访问的就是全局域,这么看的话,我在“ ::”前面换成命名空间域,不就可以访问命名空间域里的内容了吗。其实“ ::”就是命名空间使用的一种方式。

 比如我们定义了如下的命名空间:

namespace n1 
{
	int f = 0;
	int rand = 0;
}

现在该如何访问命名空间域里的内容呢?其实有3种方法:

  1. 加命名空间名称及作用域限定符“ ::”;
  2. 使用using namespace 命名空间名称全部展开;
  3. 使用using将命名空间中成员部分展开。
  • 1、加命名空间及作用域限定符“ ::”
int main()
{
	printf("%d\n", n1::f); //0
	printf("%d\n", n1::rand);//0
	return 0;
}

为了防止定义相同的变量或类型,我们可以定义多个命名空间来避免。

namespace ret
{
	struct ListNode
	{
		int val;
		struct ListNode* next;
	};
}
 
namespace tmp
{
	struct ListNode
	{
		int val;
		struct ListNode* next;
	};
	struct QueueNode
	{
		int val;
		struct QueueNode* next;
	};
}

当我们要使用它们时,如下:

int main()
{
	struct ret::ListNode* n1 = NULL;
	struct tmp::ListNode* n2 = NULL;
	return 0;
}

针对命名空间的嵌套,如下:

 可以这样进行访问:

int main()
{
	struct tx::List::Node* n1; //访问List.h文件中的Node
	struct tx::Queue::Node* n2;//访问Queue.h文件中的Node
}

但是上述访问的方式有点过于麻烦,可不可以省略些重复的呢?比如不写tx::,这里就引出命名空间访问的第二种方法:

  • 2、使用using namespace 命名空间名称全部展开
using namespace tx;

这句话的意思是把tx这个命名空间定义的东西放出来,所以我们就可这样访问:

int main()
{
	struct List::Node* n1; //访问List.h文件中的Node
	struct Queue::Node* n2;//访问Queue.h文件中的Node
}

当然,我还可以再拆一层,如下:

using namespace tx;
using namespace List;
int main()
{
	struct Node* n1; //访问List.h文件中的Node
	struct Queue::Node* n2;//访问Queue.h文件中的Node
}

展开时要注意tx和List的顺序不能颠倒

这种访问方式是可以达到简化效果,但是也会存在一定风险:命名空间全部释放又重新回到命名冲突

 所以针对某些特定会出现命名冲突问题的,需要单独讨论:

由此我们得知:全部展开并不好,我们需要按需索取,用什么展开什么,由此引出第三种使用方法。

  • 3、使用using将命名空间中成员展开

针对上述代码,我们只放f出来:

namespace n1
{
	int f = 0;
	int rand = 0;
}
using n1::f;
int main()
{
	f += 2;
	printf("%d\n", f);
	n1::rand += 2;
	printf("%d\n", n1::rand);
}
  • 下面来看下C++的标准库命名空间:
#include<iostream>
using namespace std; //std 是封C++库的命名空间
int main()
{
	cout << "hello world" << endl; // hello world
	return 0;
}

如若省去了这行代码:using namespace std;

想要输出hello world就要这样做:

#include<iostream>
int main()
{
	std::cout << "hello world" << std::endl;
	return 0;
}

当然也可以这样:

#include<iostream>
using std::cout;
int main()
{
	cout << "hello world" << std::endl;
	return 0;
}

这就充分运用到了命名空间。

 

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

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

相关文章

带你见见红黑树-概念+插入篇

写的不好&#xff0c;见谅~ 目录 概念理解 红黑树规则 AVL树与红黑树的相爱相杀 红黑树的插入时的上色与旋转。 不上色&#xff08;shǎi&#xff09; 情况一&#xff1a;空树 情况二&#xff1a;非空树&#xff0c;父节点为黑 上色&#xff08;shǎi&#xff09; 情况…

【Linux】深入理解文件系统

系列文章 收录于【Linux】文件系统 专栏 关于文件描述符与文件重定向的相关内容可以移步 文件描述符与重定向操作。 可以到 浅谈文件原理与操作 了解文件操作的系统接口。 想深入理解文件缓冲区还可以看看文件缓冲区。 目录 系列文章 磁盘 结构介绍 定位数据 抽象管理…

【Linux】MySQL 高级 SQL 语句 (二)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 MySQL 高级 SQL 语句 连接查询CREATE VIEW 视图UNION 联集交集值无交集值CASE空值(NULL) 和 无值() 的区别正则表达式 连接查询 mysql> select * from xjz; #xjz表格 ---…

Linux5.8 MySQL主从复制与读写分离

文章目录 计算机系统5G云计算第四章 LINUX MySQL主从复制与读写分离一、概述及原理1&#xff09;什么是读写分离2&#xff09;为什么要读写分离呢3&#xff09;什么时候要读写分离4&#xff09;主从复制与读写分离5&#xff09;mysql支持的复制类型6&#xff09;主从复制的工作…

Rust语言从入门到入坑——(5)Rust 所有权

文章目录 0 引入1、所有权2、内存和分配3、移动与克隆3.1、移动3.2、克隆 4、引用与租借4.1、引用4.1、垂悬引用 5、函数中变量5.1 参数变量5.2 、返回值变量 0 引入 主要介绍Rust所有权的知识&#xff0c;涉及到变量的作用域&#xff0c;内存释放机制&#xff0c;移动&#x…

Python|Pyppeteer启动浏览器窗口,右侧出现空白区域怎么解决?(13)

前言 本文是该专栏的第13篇,结合优质项目案例持续分享Pyppeteer的干货知识,记得关注。 有些同学可能在使用pyppeteer的时候,在配置项里面,明明已经设置好了窗口最大化,而启动Chromium窗口,打开的窗口最右侧却是一大片空白区域,具体如下图所示: 那么,出现上述情况,需…

AutoGPT 英文版安装过程

自从2022年11月chatGPT的发布3.0GPT大模型&#xff0c;在中国掀起一股AI学习热潮&#xff0c;国内百度2023年4月份发布文心一言&#xff0c;把AI推上另一个高潮&#xff0c;最直接的是问答&#xff0c;我输入一句话&#xff0c;AI帮生成一段文字或一个视频&#xff0c;但是国内…

畅捷通T+ 反序列化漏洞复现(QVD-2023-13615)

0x01 产品简介 畅捷通 T 是一款基于互联网的新型企业管理软件&#xff0c;功能模块包括&#xff1a;财务管理、采购管理、库存管理等。主要针对中小型工贸和商贸企业的财务业务一体化应用&#xff0c;融入了社交化、移动化、物联网、电子商务、互联网信息订阅等元素。 0x02 漏…

Chat2DB数据AI工具开源!对数据分析师行业影响如何?

大家好&#xff0c;我是千与千寻&#xff0c;千寻目前在互联网公司担任算法工程师&#xff0c;也要经常性的和数据打交道。那么数据都存放在哪里&#xff1f;当然是数据库啦&#xff01; 说到数据库&#xff0c;我们就不得不提到一种编程语言——SQL数据语言&#xff0c;后端程…

2023年最新项目管理工具排名推荐,助你提升项目效率!

在当今快速发展的互联网时代&#xff0c;项目管理工具已经成为了越来越多企业和团队必不可少的工具之一。好的项目管理工具能够帮助团队更加高效地协同工作&#xff0c;提高工作效率&#xff0c;节省时间和成本&#xff0c;从而使得整个项目可以更快地达成预期目标。现在让我们…

微信为什么使用 SQLite 保存聊天记录?

概要 SQLite 是一个被大家低估的数据库&#xff0c;但有些人认为它是一个不适合生产环境使用的玩具数据库。事实上&#xff0c;SQLite 是一个非常可靠的数据库&#xff0c;它可以处理 TB 级的数据&#xff0c;但它没有网络层。接下来&#xff0c;本文将与大家共同探讨 SQLite 在…

【Diffusion模型系列1】DDPM: Denoising Diffusion Probabilistic Models

0. 楔子 Diffusion Models(扩散模型)是在过去几年最受关注的生成模型。2020年后&#xff0c;几篇开创性论文就向世界展示了扩散模型的能力和强大: Diffusion Models Beat GANs on Image Synthesis(NeurIPS 2021 Spotlight, OpenAI团队, 该团队也是DALLE-2的作者)[1] Various…

阿里云国际站代理商:如何优化阿里云服务器的性能和响应速度?有哪些调优策略和建议?

随着互联网的发展&#xff0c;阿里云服务器已经成为很多企业和个人的首选解决方案。然而&#xff0c;面对不断增长的需求和复杂的网络环境&#xff0c;如何优化阿里云服务器的性能和响应速度&#xff0c;提高用户体验&#xff0c;是很多用户关心的问题。本文将从以下几个方面&a…

上海阿里云代理商:如何保护阿里云服务器中的敏感数据?有哪些加密和访问控制措施?

如何保护阿里云服务器中的敏感数据&#xff1f;有哪些加密和访问控制措施&#xff1f;   一、阿里云服务器安全概述   阿里云服务器作为云计算服务的主要产品&#xff0c;其安全性备受用户关注。在实际使用中&#xff0c;保护服务器中的敏感数据是至关重要的&#xff0c;而…

Tkinter之GUI界面布局介绍

Tkinter之GUI界面布局介绍 关于Python 的Tkinter窗口基础可参见https://blog.csdn.net/cnds123/article/details/127227651 Tkinter 本身没有提供拖拽放置控件的方式创建 GUI 界面&#xff0c;而是提供了pack、grid和place三种几何管理器&#xff08;geometry manager&#x…

canvas详解05-变形

几何变换 canvas现在被大量地运用于游戏等动画领域,最主要的归功于它提供的一系列几何变换方法,使得动画更加地容易。所以其几何变换是非常重要的一节。 在本教程前面的部分中,我们已经了解了 Canvas 网格和坐标空间。到目前为止,我们只是根据我们的需要使用默认的网格,改…

Unity - 记一次,使用 RenderDoc 调试 渲染 异常 的过程

文章目录 vertex shader - rawfragment shader - raw调试RDC的shader准备选项 - remote - 不要选local先查看 texture, sampler, ubo 数据调试&#xff1a;输出原始的法线数据调试&#xff1a;输出原始法线0\~1>-1\~1&#xff0c;并应用法线强度的法线调试&#xff1a;输出世…

强化学习从基础到进阶-常见问题和面试必知必答[3]:表格型方法:Sarsa、Qlearning;蒙特卡洛策略、时序差分等以及Qlearning项目实战

【强化学习原理项目专栏】必看系列&#xff1a;单智能体、多智能体算法原理项目实战、相关技巧&#xff08;调参、画图等、趣味项目实现、学术应用项目实现 专栏详细介绍&#xff1a;【强化学习原理项目专栏】必看系列&#xff1a;单智能体、多智能体算法原理项目实战、相关技巧…

一文了解RabbitMQ安装使用

什么是RabbitMQ? 官网&#xff1a;Messaging that just works — RabbitMQ RabbitMQ是一种开源的消息中间件软件&#xff0c;用于构建可扩展的分布式应用程序。它实现了高级消息队列协议&#xff08;AMQP&#xff09;&#xff0c;这是一种网络协议&#xff0c;用于在应用程序之…

RIS 系列:TransVG: End-to-End Visual Grounding with Transformers 论文阅读笔记

RIS 系列&#xff1a;TransVG: End-to-End Visual Grounding with Transformers 论文阅读笔记 一、Abstract二、引言三、相关工作3.1 视觉定位两阶段方法单阶段方法 3.2 Transformer视觉任务中的 Transformer视觉-语言任务中的 Transformer 四、视觉定位中的 Transformer4.1 基…