【C++】命名空间

举报
修修修也 发表于 2024/03/30 12:52:06 2024/03/30
【摘要】 文章内容包括:命名空间的由来,命名空间的定义,命名空间使用的三种方式。

🎏命名空间的由来

在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;
}


📌使用using将命名空间中某个成员引入

这种命名空间的使用方式是在全局范围将命名空间中的某个成员引入,此时,该变量在工程中就相当于一个全局变量,此时在整个工程中就可以直接使用该成员了.

这种是我们一般比较推荐的命名空间使用方式,因为它既不会像单独展开那样导致代码太过繁琐,又不会像命名空间全部展开那样导致大面积的命名污染.

如下,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;
}

📌使用using namespace命名空间名称引入

这种命名空间的使用方式是在全局范围将整个命名空间引入。此时,该命名空间的所有成员都被引入到了工程中,此时在整个工程中就可以直接使用该命名空间的所有成员了.

这种方式会将命名空间里的所有成员都暴露在全局中,是我们最不推荐的一种使用方式,因为这样极易造成不经意间的命名空间污染问题.

如下,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;
}
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。