🦄个人主页:修修修也
🎏所属专栏:C++
??操作环境:Visual Studio 2022
在C++开发过程中,大型程序往往会使用多个独立开发的库,这些库又会定义大量的全局名字,如类,函数和模板等。当应用程序用到多个供应商提供的库时,不可避免地会发生某些名字相互冲突的情况。多个库将名字放置在全局命名空间中将引发命名空间污染(namespace pollution)。
如下情况,C语言是无法解决类似的冲突问题的:
#include<stdio.h>
#include<stdlib.h>
int rand = 10;
//rand是有关随机数的一个库函数
int main()
{
printf("%d\n", rand);
return 0;
}
如上代码在编译器中运行结果会有重定义错误:
传统上,程序员通过将其定义的全局实体名字设得很长来避免命名空间污染问题,这样的名字通常包含表示名字所属库的前缀部分:
class cplusplus_primer_Query{ ... };
string cplusplus_primer_make_plural(size_t,string&);
这种解决方案显然不太理想:对于程序员来说,书写和阅读这么长的名字费时费力且过于烦琐。
命名空间(namespace)为防止名字冲突提供了更加可控的机制。命名空间分割了全局命名空间,其中每个命名空间是一个作用域。通过在某个命名空间中定义库的名字,库的作者(以及用户)可以避免全局名字固有的限制。
定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接一对{}即可,{}中即为命名空间的成员。
如下,我们定义了一个名为MFC的命名空间,里面包含了三个成员,分别是:变量min,函数Sum,结构体Stu:
namespace MFC
{
//命名空间中可以定义变量/函数/类型
int min = 1;
int Sum(int a, int b)
{
return a + b;
}
struct Stu
{
struct Stu* next;
char name[10];
};
}
?????? 和其他作用域类似,命名空间中的每个名字都必须表示该空间内的唯一实体。因为不同命名空间的作用域不同,所以在不同命名空间内可以有相同名字的成员。
如下A2命名空间就嵌套在A1里:
//命名空间可以嵌套
namespace A1
{
int a;
int b;
int Sum(int sum1, int sum2)
{
return sum1 + sum2;
}
namespace A2
{
int c;
int d;
int sub(int sub1, int sub2)
{
return sub1 - sub2;
}
}
}
命名空间可以定义在几个不同的部分,同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中:
这种命名空间的使用方式是仅在使用某个变量的时候去找到它存在的命名空间然后将它单独展开使用。
这种使用方式适合于只在程序中使用一两次的变量/函数/类型,这种使用方式可以有效防止命名空间大幅度展开造成的命名污染,但缺点是当该成员要使用多次时,每次都在使用时展开,会导致代码逻辑比较繁琐。
如下,这次展开的作用范围就仅仅在printf()函数中才有用:
namespace MFC
{
//命名空间中可以定义变量/函数/类型
int min = 1;
int Sum(int a, int b)
{
return a + b;
}
struct Stu
{
struct Stu* next;
char name[10];
};
}
int main()
{
printf("%d\n", MFC::min);
return 0;
}
这种命名空间的使用方式是在全局范围将命名空间中的某个成员引入,此时,该变量在工程中就相当于一个全局变量,此时在整个工程中就可以直接使用该成员了.
这种是我们一般比较推荐的命名空间使用方式,因为它既不会像单独展开那样导致代码太过繁琐,又不会像命名空间全部展开那样导致大面积的命名污染.
如下,18行使用using展开的成员min就可以在主函数内直接使用了:
namespace MFC
{
//命名空间中可以定义变量/函数/类型
int min = 1;
int Sum(int a, int b)
{
return a + b;
}
struct Stu
{
struct Stu* next;
char name[10];
};
}
using MFC::min;
int main()
{
printf("%d\n", min);
return 0;
}
这种命名空间的使用方式是在全局范围将整个命名空间引入。此时,该命名空间的所有成员都被引入到了工程中,此时在整个工程中就可以直接使用该命名空间的所有成员了.
这种方式会将命名空间里的所有成员都暴露在全局中,是我们最不推荐的一种使用方式,因为这样极易造成不经意间的命名空间污染问题.
如下,18行使用using namespace展开的命名空间MFC里的成员就可以在主函数内直接使用了:
namespace MFC
{
//命名空间中可以定义变量/函数/类型
int min = 1;
int Sum(int a, int b)
{
return a + b;
}
struct Stu
{
struct Stu* next;
char name[10];
};
}
using namespace MFC;
int main()
{
printf("%d\n", min);
printf("%d\n", Sum(1, 2));
return 0;
}
希望这篇命名空间的简介能对大家有所帮助,欢迎大佬们留言或私信与我交流.
学海漫浩浩,我亦苦作舟!关注我,大家一起学习,一起进步!
相关文章推荐