【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;
}
相关推荐
Pdh胖大海几秒前
天源迪科java实习生面经
java·开发语言
安亿10324 分钟前
linux下的日志编写
linux·服务器·c语言·软件构建
咩咩大主教26 分钟前
C++在Linux实现多线程和多进程的TCP服务器和客户端通信
linux·服务器·c语言·开发语言·c++·网络协议·tcp/ip
冰暮流星37 分钟前
继承的例题
开发语言
麻木的根号三37 分钟前
【C++初阶】探索STL之——vector
java·开发语言·c++
学步_技术42 分钟前
Python编码系列—Python代理模式:为对象赋予超能力的魔法
开发语言·python·代理模式
FITMT1 小时前
STL之vector
开发语言·c++·笔记
Midsummer啦啦啦1 小时前
网址匹配正则表达式(python实现)
开发语言·python·正则表达式
web安全工具库1 小时前
深入理解Python中的时间表示:Unix时间点、毫秒和微秒,以及time模块
开发语言·python·unix
艾伦~耶格尔1 小时前
Java API 之集合框架进阶
java·开发语言·学习