21天学会C++:Day2----命名空间的那些事儿

news2024/10/6 4:14:13

· CSDN的uu们,大家好。这里是C++入门的第二讲。
· 座右铭:前路坎坷,披荆斩棘,扶摇直上。
· 博客主页: @姬如祎
· 收录专栏:C++专题

目录

1. 为什么要有命名空间

2. 命名空间的定义

3. 访问命名空间域中成员的三种方式

3.1 使用using namespace 命名空间名称 引入

3.2 使用using将命名空间中某个成员引入

3.3 加命名空间名称及作用域限定符

4. 命名空间的其他知识

4.1 命名空间的合并

4.2 命名空间的嵌套

5. 总结


 

 我们通过了解C++的发展史知道了C++的诞生的原因:为了弥补C语言的不足。因此在C++的入门阶段我们主要学习的就是C++是如何弥补C语言的缺陷的。

1. 为什么要有命名空间

我们先来看这样一段代码:

#include<stdio.h>
#include<stdlib.h>

int rand = 0;

int main()
{
	printf("%d\n", rand);

	return 0;
}

运行之后会报错:

这是为什么呢?因为头文件中有一个 rand() 函数的定义,我们知道头文件的包含在预处理阶段会将其里面的代码copy过来 。在编译阶段,既有一个全局变量rand,又有一个rand()函数的定义,显然就会报错啦!报错提示的C2365中的C就是Compile 编译的意思,代表编译阶段出错。

到这里可能就有人会说,我知道头文件 stdlib.h 中有rand的定义,我就不会去定义一个全局的rand了。但是呢,头文件这么多,保不齐你哪天包含一个头文件之后,代码就出现了99+的错误。还有就是一个大的项目不可能是由一个人完成的撒,不同的人对函数和变量的命名很有可能是相同的,在各自的项目进行合并是,又可能出现一对错误。这就是C语言的缺陷。因此C++中有了命名空间的概念。

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

2. 命名空间的定义

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

在这里还得提到一个域的概念:在C语言中我们学习了全局域,局部域。我们在C++中还会接触到命名空间域,类域等等。一个变量所处域的不同会影响其声明周期。

我们来看C++是如何解决上述面命名冲突的问题的。大家可以猜猜看这段代码在终端的输出。

int a= 0;
namespace Tchey_Y
{
	int a= 1;
}

int main()
{
	int a= 2;
	printf("%d\n", rand);
	return 0;
}

 没错就是2,原因是编译器在查找变量时有先从局部域中搜索,然后才是全局域。这里值得注意的是:不加任何限定的话,编译器是不会在命名空间域中去搜索的。

 那我们怎么才能做到局部域有这个变量的同时还能去访问到全局的同名变量呢?这里就得使用我们的作用域限定符啦:::。就是两个英文状态下的分号,加上这个域作用限定符,就能实现在该作用域下搜索变量。如果该作用域下没有这个变量就会报错。

int a = 0;
namespace Tchey_Y
{
	int a = 1;
}

int main()
{
	int rand = 2;
	printf("%d\n", a); //访问局部域的变量a
	printf("%d\n", ::a); //访问全局域下的a
	printf("%d\n", Tchey_Y::a); //访问命名空间域下的a

	return 0;
}

域作用限定符的左边什么都不写就代表在全局域下搜索。

3. 访问命名空间域中成员的三种方式

3.1 使用using namespace 命名空间名称 引入

我们在看C++的代码时,代码开头是不是都有这么一句:

using namespace std;

 这便是将命名空间域进行展开。将命名空间进行展开之后,如果你的全局域中有与该命名空间域同名的变量和函数依旧时会报错的。

 为什么会这样呢?编译器默认是不会去命名空间域搜索a这个变量的,当我们展开命名空间之后,对于上面的程序编译器就会在命名空间域中和全局域中同时搜索变量a。全局域与命名空间域中都有一个a,自然就会报错啦!

这样也显示出使用 using namespace 的坏处。因此在实际的工程中我们是不会使用这种方式去访问命名空间域中的成员的。

在C++中,C++的标准库,以及STL都是在std这个命名空间下的,因此在using namespace std 之后我们就能使用std命名空间域中的成员啦。但是这些东东不是在同一个头文件中的,使用时我们还需要包含对应的头文件。

3.2 使用using将命名空间中某个成员引入

直接展开命名空间不好,那有没有什么更加好的方式呢?显然是有的,我们可以 单独引入命名空间下的某个成员。这样就不容易发生冲突啦!

#include<iostream>

using std::cout;
using std::endl;

int main()
{
	cout << "hello world" << endl;
	return 0;
}

 这里我们引入了命名空间中的cout和endl,这样我们就能使用std命名空间中的cout和endl了,但是这样就不能使用std命名空间中的其他成员,比如cin。cout,cin是分别是ostream和istream的对象,关于这点我们后面会学习到。智力只需要知道cout是输出,cin是输入,endl是换行即可。

这么做是不错,可是当我们使用std命名空间下的很多成员之后,就和直接展开命名空间没啥区别了,因此我们可以和第三种访问命名空间成员的方法配合使用。

3.3 加命名空间名称及作用域限定符

这种方法我们上面就已经使用过了。

#include<iostream>
#include<vector>

using std::cout;
using std::endl;

int main()
{
	cout << "hello world" << endl;
	cout << "hello world" << endl;
	cout << "hello world" << endl;
	cout << "hello world" << endl;
	cout << "hello world" << endl;
	std::vector<int> array;
    return 0;
}

程序中使用较多的成员我们选择第二种方法来访问,程序中使用较少的成员我们选择使用命名空间加上作用域限定符来访问。

4. 命名空间的其他知识

4.1 命名空间的合并

上面提到了C++的标准库和STL(标准模板库)都是在std命名空间下的,但是他们却在不同的头文件,这就是因为相同的命名空间会进行一个合并操作。

 我们在Test.h 中有一个同名的命名空间,展开之后,我们能够同时访问到这两个同名的命名空间中的成员。可以证明进行了相同命名空间的合并。

4.2 命名空间的嵌套

命名空间是可以进行嵌套的。

#include<iostream>
using namespace std;

namespace test1
{

	int a = 10;
	namespace test2
	{
		int a = 20;
	}
}

int main()
{
	cout << test1::a << endl;
	cout << test1::test2::a << endl;
	return 0;
}

 应用场景:在做一个大型的项目时,我们一般会以这个项目的名称定下一个命名空间。这个项目的完成可能是由不同的工程师完成的,工程师在做自己的那部分工程时,可能又会在这个项目的命名空间之下创建一个新的命名空间。

5. 总结

std命名空间的使用惯例:
std是C++标准库的命名空间,如何展开std使用更合理呢?

1. 在日常练习中,建议直接using namespace std即可,这样就很方便。
2. using namespace std展开,标准库就全部暴露出来了,如果我们定义跟库重名的类型/对
象/函数,就存在冲突问题。该问题在日常练习中很少出现,但是项目开发中代码较多、规模
大,就很容易出现。所以建议在项目开发中使用,像std::cout这样使用时指定命名空间 +
using std::cout展开常用的库对象/类型等方式。

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

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

相关文章

基于Java+SpringBoot+vue的人职匹配推荐系统设计与实现【源码(完整源码请私聊)+论文+演示视频+包运行成功】

博主介绍&#xff1a;专注于Java技术领域和毕业项目实战 &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3fb; 不然下次找不到哟 Java项目精品实战案例&#xff08;300套&#xff09; 目录 一、效果演示 二、…

virtualbox如何配网

配网搞了一天&#xff01;&#xff01;&#xff01; 百度到的所有教程都是垃圾&#xff01;&#xff01; 就没有一个写全的&#xff01;&#xff01;写明白怎么配的&#xff01;&#xff01;&#xff01; 我自己来&#xff01;&#xff01;&#xff01;不会配的看我&#xf…

浅析 Queue 和 Deque

终于开始了 LeetCode 的练习&#xff0c;看到 102. 二叉树的层序遍历 有种解法利用到了队列&#xff0c;想着挨个看看基础队列中的方法&#xff0c;便有了这篇文章。 基于 Java 对 Queue 以及 Deque&#xff08;double ended queue&#xff09; 实现进行学习介绍&#xff0c;JD…

Vue之代码传送(teleport)

代码传送是啥 在Vue中&#xff0c;代码传送就是将某部分的代码从Vue的template标签下传送到指定的地方&#xff0c;这个地方通常是body标签下。在使用Vue编写界面时&#xff0c;我们都是在html的Body中写一个div&#xff0c;然后指定一个id&#xff0c;然后在Vue的实例中的tem…

2023春招offer收割机,阿里架构师耗时半月写的《Java面试手册》

程序猿在世人眼里已经成为高薪、为人忠诚的代名词。 然而&#xff0c;小编要说的是&#xff0c;不是所有的程序员工资都是一样的。 世人所不知的是同为程序猿&#xff0c;薪资的差别还是很大的。 众所周知&#xff0c;目前互联网行业是众多行业中薪资待遇最好的&#xff0c;包…

Java语法理论和面经杂疑篇《九. 网络编程》

目录 1. 网络编程概述 1.1 软件架构 1.2 网络基础 2. 网络通信要素 2.1 如何实现网络中的主机互相通信 2.2 通信要素一&#xff1a;IP地址和域名 2.2.1 IP地址 2.2.2 域名 2.3 通信要素二&#xff1a;端口号 2.4 通信要素三&#xff1a;网络通信协议 2. 谈传输层协议…

时间序列教程 四、自回归和移动平均模型

一、本节目标 了解自相关函数(ACF)。 了解部分自相关函数(PACF)。 了解自回归和移动平均模型是如何工作的。 使用Python来拟合自相关模型。 二、ACF和PACF 1、自相关函数(ACF) 测量信号与自身延迟数据的相关性。 它用于发现信号中的重复模式,例如周期性信号的存…

Spring相关概念

Spring家族 官网&#xff1a;Spring | Home&#xff0c;从官网我们可以大概了解到&#xff1a; Spring能做什么:用以开发web、微服务以及分布式系统等,光这三块就已经占了JavaEE开发 的九成多。Spring并不是单一的一个技术&#xff0c;而是一个大家族&#xff0c;可以从官网的…

.NET基础加强第七课--文件流

序列化 JSON序列化 例子 using Nancy.Json; Person p1 new Person(); p1.Name “zs”; // json 序列化 JavaScriptSerializer javaScriptSerializer new JavaScriptSerializer(); string json javaScriptSerializer.Serialize(p1); Console.WriteLine(json); Console.…

linux-创建子进程的过程与原理(fork讲解)

我们知道&#xff0c;子进程可以被命令行创建&#xff0c;被fork函数创建&#xff0c;但是子进程创建了什么呢&#xff0c;是完全拷贝父进程函数&#xff1f;还是继承父进程数据呢&#xff1f; 首先我们要知道&#xff0c;进程的构成&#xff1a;进程内核数据结构可运行程序载…

二维差分【算法推导,图文讲解清晰】

798. 差分矩阵 - AcWing题库 算法推导 二维差分相对一维差分会复杂一点&#xff0c;而且还要结合二维前缀和的一些细节处理 A、B数组角色问题 在差分思想中&#xff0c;构造并不是那么重要&#xff0c;而是其中A、B数组的角色。 我们假想存在一个数组B&#xff0c;输入的A…

论文阅读《NeRF-Supervised Deep Stereo》

论文地址&#xff1a;https://arxiv.org/pdf/2303.17603.pdf 源码地址&#xff1a;https://nerfstereo.github.io/ 概述 针对深度估计的标签数据难以获取&#xff0c;自监督方法在病态&#xff08;遮挡、非朗伯面&#xff09;区域的表现差&#xff0c;跨域泛化能力弱的问题&…

【jvm系列-06】深入理解对象的实例化、内存布局和访问定位

JVM系列整体栏目 内容链接地址【一】初识虚拟机与java虚拟机https://blog.csdn.net/zhenghuishengq/article/details/129544460【二】jvm的类加载子系统以及jclasslib的基本使用https://blog.csdn.net/zhenghuishengq/article/details/129610963【三】运行时私有区域之虚拟机栈…

Vue——组件基础

目录 定义一个组件​ 使用组件​ 传递 props​ 监听事件​ 通过插槽来分配内容​ 动态组件​ DOM 模板解析注意事项​ 大小写区分​ 闭合标签​ 元素位置限制​ 组件允许我们将 UI 划分为独立的、可重用的部分&#xff0c;并且可以对每个部分进行单独的思考。在实际应…

Learning to summarize from human feedback导读(1)

总结&#xff1a; &#xff08;1&#xff09;生成摘要等模型&#xff0c;虽然有评估方法&#xff0c;但是人类总结的质量依旧难以相比 总结&#xff1a; &#xff08;1&#xff09;在各种NLP任务中&#xff0c;大规模语言模型的预训练以及取得了很高的性能 &#xff08;2&am…

PHP快速入门09-正则相关,附一定要学会的20个高频使用案例

文章目录前言一、正则表达式介绍二、正则高频案例20个2.1 检查字符串是否以字母开头2.2 检查字符串是否以数字开头2.3 检查字符串是否包含特定字符2.4 检查字符串是否以特定字符结尾2.5 检查字符串是否为纯数字2.6 检查字符串是否为纯字母2.7 检查字符串是否为有效的电子邮件地…

Bean对象的作用域和生命周期

文章目录&#xff1a;一.Bean的作用域 (1)Bean作用域的含义 &#xff08;2)Bean的6种作用域 二.Bean的生命周期&#xff08;1&#xff09;开辟内存空间 &#xff08;2&#xff09; 属性注入 &#xff08;3&#xff09;初始化 &#xff08;4&#xff09;使用Bean &#xff08;…

【CSDN|每日一练】运输石油

目录 运行结果题目描述输入描述:输出描述:示例代码结语运行结果 题目描述 某石油公司需要向A、B两地运输石油。 两地的需求量不同,而一辆车只能装载一定量的石油。 经过计算A地需要a辆车,B地需要b辆车运输才能满足需求。 现在一共有n辆车分布在各地,每辆车前往A、B两地…

HFSS一些使用技巧总结

1. 快捷键&#xff1a; CTRLH&#xff0c;隐藏选择的object、face 字母E&#xff0c;选择edge&#xff08;线&#xff09; alt左键双击九个区域&#xff0c;切换9个不同的视角&#xff08;与789组合使用) 2. 复制&#xff1a; 这样的复制好处在于&#xff1a;复制完的物体相…

使用Excel打造一款个人日志系统

写在前面 我很多年前看过晨间日志的奇迹这一本书&#xff0c;我深受启发&#xff0c;这本书的中心思想就是通过九宫格的方式写连体日志&#xff0c;自己可以方便查找而有而且有激情去完成这个日志&#xff0c;书中推荐的方法是使用excel写日志。但是自己总感觉用excel过于麻烦…