1:命名空间
C++就是延续C语言的一些不足进行改进和优化,也是一门值得我们深入探索和钻研的编程语言。它就像一个充满宝藏的宝库,等待着我们去发掘其中的奥秘和惊喜.那么就让我们来打开C++的大门,进行探索吧!!!
首先,C++要在C语言优化的第一个问题:命名冲突, 那么C语言是具体怎么冲突的呢?请看下述代码:
#include<stdio.h>int rand = 1;int main()
{printf("%d\n", rand);return 0;
}
在上述代码中,可以看到我们定义了一个全局的整形变量:rand并赋值为1:然后在main函数中进行打印,显而易见会打印出一个大大的"1",那么有小伙伴就要问了,命名冲突在哪呢?别急,请看下述代码:
#include<stdio.h>
#include<stdlib.h>int rand = 1;int main()
{printf("%d\n", rand);return 0;
}
在上述代码中,我们只是多包含了一个头文件<stdlib.h>,这会有什么区别呢?勤于动手的小伙伴会发现这样的代码在我们本地的IDE上会报错,咦~那是为什么呢?
细心的小伙伴会发现"rand"这个变量名字有点熟悉啊,这不就是生成伪随机数的rand函数吗?而此时我们又悄然的包含了rand函数的头文件,哦!!!真相只有一个,这样写的话,你想让它打印的是<stdlib.h>库里面的rand函数呢?还是全局里的rand的整形变量呢?这时IDE没有了唯一打印路径,就会分歧,从而报错了,到此真相大白了.
1.1 命名空间定义:
那么应该怎么解决呢?这时我们C++祖师爷Bjarne Stroustrup博士就发现并解决了这个问题,怎么解决的呢?接下来就引入我们的主题------命名空间
在学习命名空间之前,我们要认识一下它的关键字"namespace",多说无意,请看示例代码:
#include<stdio.h>
#include<stdlib.h>namespace MyNamespace
{int rand=1;
}int main()
{printf("%d\n",rand);// rand函数的地址printf("%d\n",MyNamespace::rand);// 1 return 0;
}
这里我们定义了一个名为"MyNamespace"的命名空间,那么它是如何解决命名冲突的问题呢?让我来一一揭晓:
在"MyNamespace"的命名空间中我们也定义了一个rand的整形变量,并赋值为1,以作区分.这时我们继续包含<stdlib.h>的头文件,这时我们上述代码中的第一处打印就不存在分歧了,打印的就是rand函数的地址数据了,
在介绍第二处打印时要先介绍一个全新的操作符"::"作用域解析运算符,那么它是怎么使用的呢?,很简单:"命名空间的名字+要访问的元素''在上述代码中,我们这样写"MyNamespace::rand"就是要访问名为MyNamespace的命名空间中的rand元素.
那么这样的话就和<stdlib.h>库中的rand函数就分开了,问题也就解决了
1.2 命名空间使用 :
命名空间作用就这吗?当然不止于此啦,在C/C++中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存 在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化, 以避免命名冲突或名字污染,namespace关键字的出现就是针对这种问题,除此之外:命名空间中可以定义变量/函数/类型,那么具体怎么用呢,上代码:
namespace MyNamespace
{// 命名空间中可以定义变量/函数/类型int rand = 10;int Add(int left, int right){return left + right;} struct Node{struct Node* next;int val;};
}
命名空间中还可以写入函数和结构体等等等...当然命名空间还可以进行嵌套:
namespace N1
{int a;int b;int Add(int left, int right){return left + right;}namespace N2{int c;int d;int Sub(int left, int right){return left - right;}}
}
在上述代码中:我们在N1的命名空间中,嵌套了一个N2的命名空间:
相同的名字的命名空间编译器会自动合并哦~:
需要注意的是:一个命名空间就定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间中
当我们要多次使用"::"作用域解析运算符,一直这样写会有点烦,那么我们就要介绍下一个关键字"using"展开命名空间,它的作用是什么呢?
//使用using namespace 命名空间名称 引入
using namespce N;
int main()
{printf("%d\n", N::a);printf("%d\n", b);Add(10, 20);return 0;
}//使用using将命名空间中某个成员引入
using N::b;
int main()
{printf("%d\n", N::a);printf("%d\n", b);return 0;
}
在上述代码中:using namespce N;可以将命名空间N:进行展开,当我们多次访问命名空间中的数据时就不用一直使用"::"这个操作符了.
当然,我们还可以不完全展开这个命名空间中的所有数据,可以只展开其中的某个类型/变量/函数,这样已达到精确的目的.使用“using namespace namespace_name;”可以将指定命名空间中的所有标识符引入到当前作用域,这样在当前作用域中就可以直接使用该命名空间中的元素而无需添加命名空间前缀。但过度使用可能导致命名冲突风险增加(建议少用全部展开,特别是在公司中多人协助做项目时,防止命名冲突)
到此有关命名空间的所有有关知识都详细的讲述了一遍,希望这篇博客能给您带来一些启发和思考!那我们下次再一起探险喽,欢迎在评论区进行讨论~~~