【C++修炼之路 第一章:入门】命名空间namspace 和 cin/cout 输入输出流

一、关于命名空间 namespace (C++关键字)

1、概念

 ​ 在C/C++中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染,namespace关键字的出现就是针对这种问题的。

简单来说就是,不同的命名空间中,可以取相同的命名

 ​ 例如项目组中程序员小明和小红,他们负责一个项目组中的不同模块,小明和小红各自设计了一个函数,他们都给函数取名叫做 “秃头函数”。但是因为项目最后合并,不能出现同一个命名,而小明和小红又不想修改自己的“创意名字”,此时就能使用 “命名空间namespace ”,小明创造一个命名空间namespace:明的空间,小红创造一个命名空间namespace:红的空间,然后他们各自往自己的 命名空间中,写入对应想取的名字,而不会造成因重复而报错
在这里插入图片描述



在.c 和 .cpp 文件中,编译器编译时:会按照下面的默认顺序查找 变量

1、当前的局部域(局部变量的家)

2、全局域(全部变量的家)

​ (默认顺序为第二位,若想直接定位到 全局域,可以在变量前加上双冒号:“::”)

printf("%d", tmp::a);  // 命名空间名字+双冒号+变量名



但是默认不会直接到其他命名空间中找

如图:不会直接到其他命名空间中找,直接报错:未声明该变量



2、使用命名空间

解决办法:直接指定到目标命名空间中找

函数 等等其他的东西都可以塞进自己的命名空间中





命名空间:可以定义变量、函数、结构,甚至是嵌套多个命名空间(套娃)

 ​ 同时,多个文件可以使用同一个命名空间编译时会将同一命名空间的进行合并

合并后就属于同一个域,则一个命名空间中也不允许出现重名

核心就是定义了一个新的作用域:同域不重名




3、命名空间展开:不想写前缀

问题又来了,老是写命名空间的前缀,不免有些麻烦



此时就可以使用:using namespace tmp; (这个叫做:展开命名空间)

将我们刚刚举例的命名空间 tmp 展开

作用:我们之前提到,编译时默认先到局部,再到全局,而不会默认去命名空间(除非自己指定)

而 命名空间展开,就可以将其变成:默认寻找(即默认第三步会到命名空间中寻找,前两步是局部和全局)

这样之后,就不用老是写 tmp:: 这种前缀了



4、多个命名空间展开:也可能会重定义报错(这是展开命名空间的坏处)

但是问题又来了,当有多个不同的命名空间同时展开,而不同的空间中存在 同名变量

则会发生重命名冲突

因此,命名空间还是别随便展开了,直接指定 就好了(又回到开头了doge)



5、部分命名空间展开

前面第 4 点中,提及的 命名空间展开 是将命名空间全部展开,这种会有重定义的风险,所以我们一般需要 自己手动指定

但是在一个命名空间中,我们可能会频繁使用某一个变量,而较少使用到其他的:使得频繁使用的那个变量,老是要写 tmp:: 就显得麻烦

例如:频繁使用 变量 a,只使用一次 变量 b

#include<stdio.h>

namespace tmp
{
	int a = 3;`在这里插入代码片`
	int b = 4;
}

int main()
{
	// 需要频繁使用 变量 a
	printf("%d", tmp::a);
	printf("%d", tmp::a);
	printf("%d", tmp::a);
	printf("%d", tmp::a);
	printf("%d", tmp::a);
	// 只需要使用一次 变量 b
	printf("%d", tmp::b); 
	return 0;
}

解决办法:对频繁使用的变量,单独处理:指定展开某一个

using tmp::a;   // 部分展开
#include<stdio.h>

namespace tmp
{
	int a = 3;
	int b = 4;
}
using tmp::a;   // 部分展开
int main()
{
	// 需要频繁使用 变量 a
	printf("%d\n", a);
	printf("%d\n", a);
	printf("%d\n", a);
	// 只需要使用一次 变量 b
	printf("%d", tmp::b); 
	return 0;
}



6、总结和一些问题解决

局部域

全局域

命名空间

不同域可以定义同名的变量/函数/类型

命名空间会不会影响生命周期?

注意:命名空间只是单纯的名字隔离,不会像局部和全局那样,影响生命周期

命名空间中定义的,拥有全局的生命周期

但是 命名空间展开,还是属于 命名空间域,不是 全局域,只是有了 全局的生命周期

为什么平时见到的 C++ 程序一般都是直接 using namespace std; 直接全部展开?

因为写 OJ 题等等操作,直接全部展开比较方便,一般可以 直接展开来用

但要注意在项目开发中,全部展开容易冲突

使用场景不同,决定是否可以使用


二、I/O输入输出流

1、基础知识

1、C++ 中的 输入输出:cin 和 cout ,其中的 c 指 console 控制台(在 linux 中,称为 终端)

2、使用 cout 标准输出对象(控制台)和 cin 标准输入对象(键盘)时,必须包含< iostream > 头文件 以及按命名空间使用方法使用 std。

3、cout 和 cin 是全局的流对象,endl 是特殊的C++符号,表示换行输出(C语言中的 ‘\n’),他们都包含在包含< iostream >头文件中

4、<< 是流插入运算符,>> 是流提取运算符。cin >> 从控制台 提取数据 ,cout << 向控制台 插入数据

5、 使用C++输入输出更方便,不需要像 printf/scanf 输入输出时那样,需要手动控制格式。 C++的输入输出可以自动识别变量类型。

​ 但是 C++ 如何控制精度之类的呢(C语言可以写 %.2这样控制精度),C++ 有专门一套函数这里暂时不讨论


2、官方的命名空间 std

 ​ 因为 C++ 官方将C++库中的所有命名全部包含在 官方的命名空间 std 中,避免重复(头文件中的也都包含在其中)
而 如果不写 using namespace std; 则编译器只会默认到 局部域和全局域 寻找,自然找不到 举例的 cout

注意:C语言中 .h 头文件展开后,是放到全局域中的,则编译器可以找到,而 C++ 中 头文件中的变量放到 命名空间中,属于命名空间域,则需要展开命名空间,所以若不展开 命名空间,编译器就找不到 这类变量




3、如何使用官方的命名空间 std:(方法前面都提到过)

1、全部展开:using namespace std;

2、指定命名空间:std::

3、指定展开某一个:using std::cout


4、std 命名空间的使用惯例:

如何展开std使用更合理呢?

1、在日常练习中,建议直接using namespace std即可,这样就很方便。

2、using namespace std展开,标准库就全部暴露出来了,如果我们定义跟库重名的类型/对 象/函数,就存在冲突问题。该问题在日常练习中很少出现,但是项目开发中代码较多、规模 大,就很容易出现。所以建议在项目开发中使用,像 std::cout 这样使用时指定命名空间 + using std::cout 展开常用的库对象/类型等方式。



5、关于为什么C++中头文件没有 .h 后缀

​  ​ 早期标准库将所有功能在全局域中实现,声明在.h后缀的头文件中,使用时只需包含对应 头文件即可,后来将其实现在std命名空间下,为了和C头文件区分,也为了正确使用命名空间, 规定C++头文件不带.h;旧编译器(vc 6.0)中还支持格式,后续编译器已不支持,因 此推荐使用+std的方式。



  • 9
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值