【C++】命名空间 以及 如何理解using namespace std;

目录

命名空间

1.由来

2.概念

3.使用

方法一

方法二

方法三

4.嵌套使用


命名空间

        很多人在学习C++的时候,第一个代码想必是如下样子的。和C语言相比,库函数换了,同时多了一个 using namespace std; 但是,你真的了解 using namespace std; 的真实作用吗?去掉 using namespace std; 会有什么影响呢?一定要加上这句话,才可以完整地打出一个Hello World 程序吗?有没有不加的办法?还是老师说要加上这句话,于是就加了。
        如果对于前面的问题,你都理解了,那么很遗憾,本篇内容不是为你准备的。如果你并不知道,并且你也想了解它们,那么恭喜你,本文的内容就是为你而准备的!

#include<iostream>
using namespace std;

int main()
{
	cout << "Hello World!" << endl;
	return 0;
}

1.由来

        我们知道,C++起初是Bjarne Stroustrup博士在C语言的基础上,不断加入新的特性产生的。那么C++肯定是为了弥补C语言的一些不足之处。那么命名空间是为了解决C语言的什么问题呢?

        我们看到下面左右两边的程序,右边相比于左边上面的,多了一行包含 stdlib.h 的头文件,就报错了,并且错误信息也在下方——“rand” 重定义。很容易联想到,stdlib.h 库里面是有 rand 函数的,我们可以用来生成随机数,那么就是自定义的全局变量名,和库里面的变量名冲突了。但是,我们将这个 rand 变量放到 main 函数内部,让它成为局部变量,就没有这个问题。这是因为,stdlib.h 是在全局域里面的,如果定义全局变量 rand,那么该变量也在全局域,自然会发生冲突,但是如果相同的名字,一个在全局域一个在局部域,就不会冲突。又比如两个不同的函数里面,都定义了 int a; 变量,也是可以的。

         与此同时,如果在一个项目组里面,组内成员分别负责不同板块的代码编写。如果组员A 和 组员B 都使用 Add 作为某个函数的函数名,或者是起了相同名字的变量(全局)等等,那么最后项目汇总起来,也会报错。

        所以,C语言在这方面会产生两个主要的问题,一是自己定义和库里面的名字冲突;二是项目组里面,多个人之间的名字冲突。为了解决这个问题,博士就在C++里面加上了命名空间这一概念,命名空间是唯一识别的一套名字,这样当对象来自不同的地方但是名字相同的时候就不会含糊不清了。

2.概念

        命名空间定义的实际上是一个,这个域相当于在全局域的基础之上,又加了一层域,就是命名空间域。并且,命名空间只影响其内部的变量,函数等等的使用不影响生命周期。上面讲到,同一个域里面不可以有同名变量,但是不同的域里面可以有。那么定义了命名空间,增加出来的命名空间域,就可以解决上面的问题。假设一个组里面有A、B两个人写代码,A将他的代码放到 A域 里面,B将他的代码放到 B域 里面,这也即使两个人定义了同名变量,也不影响。

        命名空间使用规则并不难,需要使用到关键字 namespace。如下代码,namespace 加上 该命名空间的名字,再加上花括号即可。花括号里面可以写任意的变量或者函数名,这些内容就成了该命名空间里面的,相当于和外界隔绝,如果不声明一下要使用,编译器是无法找到的,如何声明下文会讲。但是一个命名空间里面自然也是不可以有同名变量,除非是在不同的函数里面,如下。

namespace name
{
	int a;
	double b;
	char c;

	int Add(int m, int n)
	{
		int a = m + n;
		return a;
	}

	int Minus(int m, int n)
	{
		int a = m - n;
		return a;
	}

}

        如下,左边两个是头文件,右边的是.cpp 文件,将两个头文件包含进去,写出Hello World 的代码,也报错,原因如下,struct Node 和 m 重定义。

        但是我们把两个头文件,分别放到两个命名空间,就可以避免这个问题。

3.使用

         上面讲到,如果不声明,编译器无法找到 命名空间里面的内容。那么如何做声明呢?有三种方法。

1.指定命名空间访问。
2.全局展开,一般情况下,不建议全局展开。
3.部分。

方法一

        首先看到平时练习最常用的,全局展开。如下图,对于命名空间 AQueue ,直接使用using namespace AQueue;  就是全局展开,相当于告诉编译器:找变量名、函数等等,除了局部域和全局域,也可以去AQueue这个域找

        但是注意下图的代码,并没有全局展开头文件List.h 里面的 BList 这个命名空间,那么是不是代表BList 这个命名空间被取消了?并不是,命名空间还在那里,只不过是编译器寻找变量名等等不会去 BList 这个命名空间里面找而已。展不展开只是影响编译的时候,编译器的查找规则

         到这里我们就恍然大悟,为什么要加上 using namespace std; 是为了将标准库全局展开std这个命名空间就是标准库专门构建的一道防线,防止自己定义的内容和标准库里面的起冲突,造成名字污染。那么如果随随便便就使用 using namespace std;  不就相当于将别人辛辛苦苦建立起来的 “长城” 给摧毁了吗?导致 std 这个命名空间形同虚设。所以,在做项目开发的时候,是不可以直接全局展开标准库的。但是如果是自己日常代码练习,就无所谓。

        如下,将 using namespace std; 注释掉,使用cout 、endl 等等关键字,下面直接报错“未定义标识符”。也可以印证上面所说的,这是因为编译器不会去 std 这个命名空间寻找内容,所以找不到。

方法二

         第二种方法是指定命名空间访问。这里涉及到一个运算符 :: 没错就是两个冒号,它的名字是域作用限定符。A::B,其含义是,B这个变量,指定到命名空间A去寻找。

        给出如下代码,请问其结果是两个都输出 10 吗?第一个,根据局部优先原则,无疑是10。但是第二个输出,由于多了一个域作用限定符,会直接在该运算符左边的命名空间去寻找变量,左边命名空间是,空实际上代表全局,所以第二个输出20。

int a = 20;

void f1()
{
	int a = 10;
	printf("%d\n", a);
	printf("%d\n", ::a);
}

        如下代码,也可以顺利输出 Hello World!不需要全局展开标准库,直接使用域作用限定符去std命名空间查找。但是这里也会产生一个问题,cout 和 endl 是经常要使用到的,所以如果不全局展开,每次都指定命名空间访问,会特别麻烦,所以有了第三种方法,部分展开。

#include<iostream>

int main()
{
	std::cout << "Hello World!" << std::endl;
	return 0;
}

方法三

        部分展开就很好用,比如对于cout,部分展开之后,可以直接使用,不需要用 :: 了。如下,using 命名空间::成员  即可。

4.嵌套使用

        当然了,命名空间也是可以嵌套的,如下图,命名空间 BList 里面嵌套使用命名空间B,在右边的 main 函数里面,可以多重嵌套使用。

        关于命名空间和using namespace std; 就介绍到这里,相信看完本文对它们的理解一定有所加深!

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力努力再努力.xx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值