【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;
}
相关推荐
小刘同学32124 分钟前
C++11 特性
c++·c11新特性
军训猫猫头24 分钟前
1.如何对多个控件进行高效的绑定 C#例子 WPF例子
开发语言·算法·c#·.net
真的想上岸啊38 分钟前
学习C++、QT---18(C++ 记事本项目的stylesheet)
开发语言·c++·学习
m0_5522008242 分钟前
《UE5_C++多人TPS完整教程》学习笔记40 ——《P41 装备(武器)姿势(Equipped Pose)》
c++·游戏·ue5
明天好,会的1 小时前
跨平台ZeroMQ:在Rust中使用zmq库的完整指南
开发语言·后端·rust
丁劲犇1 小时前
用 Turbo Vision 2 为 Qt 6 控制台应用创建 TUI 字符 MainFrame
开发语言·c++·qt·tui·字符界面·curse
旷世奇才李先生2 小时前
Next.js 安装使用教程
开发语言·javascript·ecmascript
charlie1145141912 小时前
深入理解Qt的SetWindowsFlags函数
开发语言·c++·qt·原理分析
呜喵王阿尔萨斯2 小时前
编程中的英语
c语言·c++
likeGhee3 小时前
python缓存装饰器实现方案
开发语言·python·缓存