C++ -命名空间-详解

博客主页:【夜泉_ly】
本文专栏:【C++】
欢迎点赞👍收藏⭐关注❤️

C++ -命名空间-详解

  • 1.C语言缺点之一 -- 命名冲突
  • 2.命名空间
    • 2.1定义
    • 2.2使用
      • 访问命名空间中的变量
      • 展开命名空间域
      • 指定访问命名空间域
    • 2.3其他功能
  • 3.C++ 标准库中的命名空间
    • 指定展开
  • 4.总结

1.C语言缺点之一 – 命名冲突

先来看看下面这段简单的C语言代码:

#include <stdio.h>
int rand = 0;
int main()
{printf("%d\n", rand);return 0;
}

运行结果如下:

0

毫无疑问的结果对吧,那如果我再引入这样一个头文件呢:

#include <stdlib.h>

运行结果如下图:
在这里插入图片描述
报错了 ! 原因呢?
在这里插入图片描述
命名冲突 ——如果学过C语言,那应该能知道在<stdlib.h>里面有一个函数,用于生成随机数,而这个函数的名字就是rand,此处,我也定义了同名的变量rand,这就导致了命名冲突。

在C语言中,全局域中命名冲突非常常见,主要有以下两种情况:
1.与库函数冲突:
这就是上面代码报错的原因。
在C语言项目中,可能某天引入了一个库,结果出现了一大堆冲突。
2.开发者相互之间冲突:
在大型项目中,往往都是项目组,这代表不是一个人在写。
那么有没有一种可能,张三写的和李四写的冲突了,但在他们电脑上都能跑。有一天,不同模块合并到一起,结果发现冲突了,这时必然会有一个人要改他的代码。
如果张三、李四都将这个名字在他们的代码里用了几百上千词,那么要修改将是一个极其痛苦的事情。

而C++的祖师爷,下图的本贾尼·斯特劳斯特卢普,同样受够了C语言中的这个缺点,于是在C++中,创造了一个关键字namespace ,用来解决全局域中命名冲突的问题。
在这里插入图片描述

2.命名空间

2.1定义

命名空间可以定义出一个,将其中的内存隔离在这个独立区域,不会与其他区域中的名字冲突:

namespace ly
{int rand = 0;
}

在上面的代码中,我定义了一个名为ly的命名空间,里面包含了变量rand。通过这种方式,避免了与标准库rand函数的冲突。

此处,ly是命名空间的名字,这里我取的是我博客名字【夜泉_ly】中的一部分,而一般开发中是用项目名字做命名空间名。

2.2使用

访问命名空间中的变量

在C语言的学习中,可以了解到,同一个域不能定义同名变量,而不同的域可以定义同名变量。
例如,全局作用域和局部作用域:

#include <stdio.h>
int a = 0;//全局域--全局变量
int main()
{int a = 1;//局部域--局部变量printf("%d\n", a);return 0;
}

C语言的域会影响生命周期,也会影响访问,比如上面这段代码的运行结果是1,因为优先访问的是局部变量。
那么有人问了,如果我就想访问全局变量呢?
也是有方法的:

#include <stdio.h>
int a = 0;//全局域--全局变量
int main()
{int a = 1;//局部域--局部变量printf("%d\n", ::a);return 0;
}

这里使用了域作用限定符::,其作用是对左边的域进行访问,此处::左边没有域,即左边为空白,代表对全局域进行访问。
再看下面这种情况:

#include <stdio.h>
int a = 0;//全局域--全局变量
namespace ly
{int a = 2;//命名空间域
}
int main()
{int a = 1;//局部域--局部变量printf("%d\n", a);return 0;
}

这里出现了三种域,局部域、全局域、命名空间域,按什么顺序访问?
第一次打印,结果为1,因为默认局部域优先。
再注释掉局部变量a:

//int a = 1;//局部域--局部变量

第二次打印,结果为0,因为局部域未找到指定变量时,会去全局域找。
再注释掉全局变量a:

//int a = 0;//全局域--全局变量

第三。。没有第三次打印了:
在这里插入图片描述
又报错了 ! 原因呢?
在这里插入图片描述
未声明a ——这是因为编译器并不会主动去命名空间域中搜索,所以会报错。
如何访问命名空间域呢?
一般而言,有两种方法:展开命名空间域 OR 指定访问命名空间域。

展开命名空间域

使用using关键字:

using namespace ly;

在一些C++程序开头,常常看见下面这两句代码:

#include <iostream>
using namespace std;

现在可以知道第二句在干什么了:展开了C++标准库的命名空间域。

指定访问命名空间域

printf("%d\n",ly::a);

即在域作用限定符::前加上要访问的命名空间。


现在使用第一个方法,展开命名空间域,来看看下面这段代码会输出什么值?😄

#include <stdio.h>
int a = 0;//全局域--全局变量
namespace ly
{int a = 2;//命名空间域
}
using namespace ly;//展开命名空间域
int main()
{printf("%d\n", a);return 0;
}

什么都输出不了!又报错了:
在这里插入图片描述
其实此处的两个a又冲突了:
展开命名空间域,是将命名空间域中的内容全部暴露到全局域,而同一个域不能定义同名变量,所以编译器会报错。
因此,不要轻易使用using namespace!


回到开头,如果想放心的使用rand作为变量名,可以使用命名空间,并通过指定访问命名空间域的方式访问:

#include <stdio.h>
#include <stdlib.h>
namespace ly
{int rand = 0;
}
int main()
{printf("%d\n", ly::rand);//打印rand变量的值printf("%p\n", rand);//打印rand函数的地址return 0;
}

此时可以成功输出结果,如图:
在这里插入图片描述

或许会有人问:为什么不能定义一个局部变量来解决问题?
需注意的是,此处的问题就是定义了一个全局变量,而这个全局变量与库冲突了。因此不能通过定义局部变量解决问题。


2.3其他功能

除了变量,命名空间还可以包含其他内容,例如函数、结构体等。
命名空间甚至可以嵌套使用:

namespace N1
{int a = 1;namespace N2{int a = 2;}
}

访问时也需多次使用::

printf("%d\n",N1::N2::a);//输出2

通过嵌套命名空间,开发者可以进一步组织和管理代码。


3.C++ 标准库中的命名空间

在学习C语言时,有时也会看到一些C++的代码,这时或许会产生疑问,为什么C++无.h,比如:

#include <iostream.h>

其实,在很早之前,上面这句代码是存在的,在一些老编译器(如VC6.0)上也可以运行,但那时没有命名空间,也不需要展开。

而后来为了与C语言进行区分,并且有了命名空间,C++库、STL等被封进std,这时.h就被去掉了。

现在,标准库通过std命名空间进行管理,在 C++ 的标准库中,所有的库函数和对象都封装在 std 命名空间中。
又由于默认不去命名空间进行搜索,在使用标准库时,可以选择指定访问,例如:

std::cout << "Hello World!" << std::endl;

或者展开空间:

using namespace std;
cout << "Hello World!" << endl;

需注意:这个展开并非展开头文件,因此,展开std不等于不包含头文件!!

在包含了头文件后,在预处理阶段会将其内容展开,而其内容是封在std里的,展开了std,等于告诉编译器可以去这些内容里面进行搜索。
但是,直接展开会有风险,如果自己定义的跟库重名,就会报错,这不就直接回到起点,将C语言的缺点再次包含。
因此,建议在项目中不要展开,而是指定访问;而日常练习中可以展开

而在一个项目中,可能会有百万级的代码量,每次都指定访问太过麻烦,这里就出现了一种新的玩法:

指定展开

例如:

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

只需将常用的展开,不常用的再指定访问,就能大大减少工作量。

4.总结

命名空间是 C++ 中用于解决命名冲突的一个非常重要的工具。
在编写大型项目时,开发者应尽量避免直接展开整个命名空间,而是通过指定访问或部分展开的方式来使用命名空间。
合理使用命名空间不仅能提高代码的可维护性,还能避免命名冲突带来的问题。


希望本篇文章对你有所帮助!并激发你进一步探索编程的兴趣!
本人仅是个C语言初学者,如果你有任何疑问或建议,欢迎随时留言讨论!让我们一起学习,共同进步!

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

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

相关文章

云计算实训50——Kubernetes基础命令、常用指令

一、Kubernetes 自动补齐 # 安装自动补齐软件 [rootmaster ~]# yum -y install bash-completion # 临时开启自动补齐功能 [rootmaster ~]# source # 永 久开启自动补齐功能 [rootmaster ~]# echo "source > ~/.bashrc 二、Kubernetes 基础命令 kubectl [command] …

Linux:进程(二)

目录 一、cwd的理解 二、fork的理解 1.代码共享 2.各司其职 3.fork的返回值 三、进程状态 1.进程排队 2.进程状态 运行状态 一、cwd的理解 cwd&#xff08;current working directory&#xff09;。译为当前工作目录。 在C语言中&#xff0c;使用fopen函数打开文件时&…

MindShare PCIE 3.0 笔记-第一二章

MindShare 官网&#xff0c;地址如下: MindShare Chapter 1&#xff1a;PCIE 背景介绍 - PCI 总线模型 1. 以 PCI 总线作为外设总线的 SOC 芯片架构 下图展示了一个以 PCI 总线作为外设总线的 SOC 芯片架构(PCI 总线类似 AXI 下的 AHB&#xff1f;)&#xff1a; 由上图可知…

linux下的日志编写

1、日志初始化创建 2、日志写入 3、日志关闭 log.c #include "log.h"static log_t LOG;//初始化日志文件&#xff0c;在当前目录创建日志文件 int log_init(char *pdirname) {time_t t;struct tm *ptm NULL;char filepath[64] {0};int ret 0;time(&t);ptm …

linux安全软件Hydra使用教程

Hydra 是一个强大的网络登录工具&#xff0c;常用于渗透测试&#xff0c;支持对多种服务和协议&#xff08;如 SSH、FTP、HTTP 等&#xff09;进行暴力crack攻击。它可以通过字典攻击来测试用户名和密码的有效性。以下是关于如何使用 Hydra 的基本步骤和示例&#xff1a; 1. 安…

Mapsui:一个 .NET 开源的地图组件库

前言 今天大姚给大家分享一个.NET开源&#xff08;MIT License&#xff09;、免费、同时支持多平台框架&#xff08;MAUI、WPF、Avalonia、Uno、Blazor、WinUI、Eto、.NET Android 和 .NET iOS&#xff09;地图组件库&#xff1a;Mapsui。 项目源代码 支持的UI框架的NuGet包 创…

车市状态喜人,国内海外“两开花”

文/王俣祺 导语&#xff1a;随着中秋假期告一段落&#xff0c;“金九”也正式过半&#xff0c;整体上这个销售旺季的数据可以说十分喜人&#xff0c;各家车企不是发布新车、改款车就是推出了一系列购车权益&#xff0c;充分刺激了消费者的购车热情。再加上政府政策的鼎力支持&a…

828华为云征文|部署在线文件管理器 Spacedrive

828华为云征文&#xff5c;部署在线文件管理器 Spacedrive 一、Flexus云服务器X实例介绍1.1 云服务器介绍1.2 产品优势1.3 计费模式 二、Flexus云服务器X实例配置2.1 重置密码2.2 服务器连接2.3 安全组配置 三、部署 Spacedrive3.1 Spacedrive 介绍3.2 Docker 环境搭建3.3 Spac…

MFC获取网页的html文本

使用 CInternetSession 类和 CHttpFile 类&#xff1b; 在stdafx.h中加入 #include <afxinet.h> &#xff1b; 基本的代码如下&#xff0c; void CMFCApplication3Dlg::OnBnClickedButton1() {// TODO: 在此添加控件通知处理程序代码try{CInternetSession session;CH…

Java创建教程!(*  ̄3)(ε ̄ *)

Java 构造函数 Java面向对象设计 - Java构造函数 构造函数是用于在对象创建后立即初始化对象的代码块。 构造函数的结构看起来类似于一个方法。 声明构造函数 构造函数声明的一般语法是 <Modifiers> <Constructor Name>(<parameters list>) throws <…

用户体验不好的网站都有哪些特点?

用户体验不好的网站通常具有一些共同的特点&#xff0c;这些特点会显著影响用户的浏览体验和满意度。下面详细介绍用户体验不好的网站的多个方面&#xff1a; 用户体验不好的网站都有哪些特点&#xff1f; 页面加载时间过长 用户等待时间长&#xff1a;如果一个网站的页面加载…

[Redis][Redis简介]详细讲解

目录 1.认识 Redis2.Redis 特性1.速度快2.基于键值对的数据结构的服务器3.丰富的功能4.简单稳定5.客户端语言多6.高扩展性7.持久化(Persistence)8.主从复制9.⾼可⽤和分布式 3.Redis 使用场景1.数据库2.Cache3.消息队列 4.注意 1.认识 Redis Redis是⼀种基于键值对(Key-Value)…

OpenHarmony(鸿蒙南向开发)——标准系统方案之瑞芯微RK3566移植案例(下)

往期知识点记录&#xff1a; 鸿蒙&#xff08;HarmonyOS&#xff09;应用层开发&#xff08;北向&#xff09;知识点汇总 鸿蒙&#xff08;OpenHarmony&#xff09;南向开发保姆级知识点汇总~ OpenHarmony&#xff08;鸿蒙南向开发&#xff09;——轻量系统STM32F407芯片移植案…

PyQt5-QCheckBox-开关按钮

效果预览 实现代码 from PyQt5.QtWidgets import QCheckBox, QApplication, QWidget, QVBoxLayout from PyQt5.QtCore import Qt, QRect, QPropertyAnimation, QEasingCurve, pyqtProperty from PyQt5.QtGui import QPainter, QColor, QPen, QFontclass CompactSwitchCheckbox…

《Google软件测试之道》笔记

介绍 GTAC&#xff1a;Google Test Automation Conference&#xff0c;Google测试自动化大会。 本书出版之前还有一本《微软测试之道》&#xff0c;值得阅读。 质量不是被测试出来的&#xff0c;但未经测试也不可能开发出有质量的软件。质量是开发过程的问题&#xff0c;而不…

股指期货的详细玩法功能与应用解析

股指期货作为一种重要的金融衍生工具&#xff0c;为投资者提供了多样化的投资和风险管理手段。本文将详细探讨股指期货的三大主要功能&#xff1a;风险规避、价格发现和资产配置。 第一&#xff0c;风险规避功能 1.套期保值&#xff1a;股指期货的风险规避功能主要通过套期保值…

HarmonyOS 速记

目录 装饰器Entry(入口)Component(组件)State(状态)Prop(属性)Preview(预览)PreviewerInspector 结构体structbuild自定义组件自定义 Custom 组件 容器Row(行) & Column(列)RelativeContainer(相对布局容器)marginpaddingSwiper(轮播图)Grid(网格容器)List(列表) 组件Image…

Java入门程序-HelloWorld

Java程序开发的三个步骤 1.编写代码得到 .java 源代码文件 2.使用javac编译得到 .class 字节码文件 3.使用java运行 注意事项 建议代码文件名全英文&#xff0c;首字母大写&#xff0c;满足驼峰命名法&#xff0c;源代码文件的后缀必须是.java 开发HelloWorld程序 &…

MATLAB十九种作图大全

一、二维曲线图 反应两个变量的因果关系 clear; %清除工作空间的所有变量 clc; %清除命令窗口的内容&#xff0c;对工作环境中的全部变量无任何影响 close all; %关闭所有的Figure窗口 x linspace(1,200,100); %均匀…

进程监控与管理详解

一、进程的定义: 进程process是正在运行的程序,包括: 分配的内存地址空间 安全属性、包括所有权和特权 一个或多个线程 进程状态 进程的环境包括: 本地和全局变量 当前调度上下文…