【C++】弥补C语言的不足(①命名冲突问题)

Hello,这里是关于C++的入门,C++的命名冲突问题,如果你像我一样对命名空间满是疑惑,只知道using namespace std,那么可以看下这篇文章,我自己之前的一些疑惑以及一些形象的理解。

命名冲突问题与命名空间

🌻命名冲突问题

首先,我们先来看一段很简单的C语言程序。

c 复制代码
#include <stdio.h>
#include <stdlib.h>
int  rand = 0;
int main()
{
	printf("%d", rand);
	return 0;
}

我们运行程序,发现程序出现了报错。如下:

rand 重定义;以前定义的是函数

我们在cpusplus.com网站上搜索rand()函数,便可简单了解。

rand()是来产生随机数的一个函数,内部使用线性同余法实现。

当我们又在程序中定义一个全局变量rand时,显然,这个变量rand与函数rand产生了命名冲突

关于命名冲突问题,既可能是我们自己定义的变量与库进行冲突,也有可能是在一个大型项目中我们彼此之间的冲突。

因此,为了解决C语言的这个问题,C++在此上进行改善。

于是C++为了解决这个问题,定义了命名空间

于是,我们可以用C++来改善我们刚刚的C语言程序。将我们的全局变量rand放进命名空间。(用命名空间将自己定义的变量"封"起来。)

这时,我们编译程序,程序没有出现报错。

当我们将我们定义的全局变量rand放进自己定义的命名空间的时候,也就是将自己定义的全局变量"封装起来",在程序运行时,访问的rand即是库函数中的rand()函数

我们打印的是rand函数的地址,将%d改成%p函数就不会报错了。

而当我们想要访问自己定义的全局变量时,我们即"指定"即可,即使用域作用限定符号::

即改成printf("%d\n",my_space::rand);即可访问变量rand(因为我们自定义的命名空间并没有打开)。

关于命名空间,我们自定义的命名空间中不仅仅可以放变量,也可以放函数、结构体等。

我们加入一个函数,进一步扩展我们的命名空间。如下:

这里需要注意的是,既然要访问my_space中的函数,那么就要用域作用限定符来指定。(因为my_space并没有全部打开,没有"暴露"出来,我们要告诉编译系统,我们使用的Add()来自哪里,让编译系统直接去找。)

若没有限定的话,那么就会出现报错。如下。

我们可以再加入结构体:

可能有的童学会想,如果在极端情况下,我们自己定义的命名空间内的变量的名字也出现了冲突怎么办?或是在一个很大的项目中,由于代码行数过多,不经意间将自己已经定义过的的变量又再次定义怎么办呢?

其实,对于命名空间,是可以进行嵌套的。从而将一个很大的命名空间内在定义几个小的命名空间,使得逻辑更清晰。同样,在小的命名空间内还可以进行进一步的嵌套。

🌻命名空间实现声明与定义的分离

下面我们来讨论一下如何用命名空间实现声明与定义的分离。

同一个文件的相同名字的命名空间一般会合并在一起。

我们用简单的栈来看。(其中压栈那个函数简单写得不严谨。)

这样将头文件和cpp文件都分别封装,不会发生命名冲突的问题。

同一个文件多个位置的同名的命名空间,编译器会把它们合并为一个。

🌻从默认指定---->展开访问---->指定展开

即展开命名空间

展开命名空间与展开头文件的区别?

展开头文件是在预处理阶段,编译系统将头文件中的内容拷贝过来。

而展开头文件,即是打开命名空间,(打开了封住它的一堵墙),将它"暴露"出来。

而仅仅展开头文件,头文件中的内容则不一定暴露出来。

比如关于C++标准库,

我们不进行展开,就会出现报错。

展开头文件仅仅是将头文件中的内容拷贝过来,但是它被C++的标准库给封装在一起,我们如果展开这个标注库std(也是一个命名空间),我们就可以自由地使用了。

但是,关于命名空间的展开,我们也要分情况。

若是我们平时的小练习,那么我们自己定义的变量和库中重命名的概率很小很小,为了方便和简洁,就可以直接展开。

但若是在一个项目中,定义变量和函数过多既有可能与库的重冲突,又有可能与其他同事的冲突,所以,不建议展开。

比如,我们写简单的输出:

我们打开标准库:

cpp 复制代码
#include <iostream>
using namespace std;
int main()
{
	cout << "hello" << endl;
	return 0;
}

也可以不打开标准库:(使用作用域限定符,指定编译系统到std命名空间去找cout。)

cpp 复制代码
#include <iostream>
int main()
{
	std::cout << "hello" << std::endl;
	return 0;
}

像上面,我们每次指定展开命名空间很不方便;直接展开,全部暴露,又有冲突风险,那么我们用指定展开解决问题。

如下:

cpp 复制代码
#include <iostream>
using  std::cout;
using  std::endl;
int main()
{
	cout << "hello" << endl;
	return 0;
}
相关推荐
小芒果_01几秒前
P11229 [CSP-J 2024] 小木棍
c++·算法·信息学奥赛
gkdpjj6 分钟前
C++优选算法十 哈希表
c++·算法·散列表
王俊山IT8 分钟前
C++学习笔记----10、模块、头文件及各种主题(一)---- 模块(5)
开发语言·c++·笔记·学习
为将者,自当识天晓地。10 分钟前
c++多线程
java·开发语言
-Even-10 分钟前
【第六章】分支语句和逻辑运算符
c++·c++ primer plus
小政爱学习!12 分钟前
封装axios、环境变量、api解耦、解决跨域、全局组件注入
开发语言·前端·javascript
k093327 分钟前
sourceTree回滚版本到某次提交
开发语言·前端·javascript
神奇夜光杯35 分钟前
Python酷库之旅-第三方库Pandas(202)
开发语言·人工智能·python·excel·pandas·标准库及第三方库·学习与成长
Themberfue37 分钟前
Java多线程详解⑤(全程干货!!!)线程安全问题 || 锁 || synchronized
java·开发语言·线程·多线程·synchronized·
plmm烟酒僧39 分钟前
Windows下QT调用MinGW编译的OpenCV
开发语言·windows·qt·opencv