解构C++高级命名空间:构建空间作用域·控制兼容

**前引:**C++作为C语言的继承者,也是其掘墓人。在编程语言的演化长河中,C++始终游走在【兼容】与【革新】的路上。C程序员眼中(高效直接)的全局函数,对于C++开发者来说是【命名空间污染的炸弹】,如果C++未发明命名空间,今天的Linux内核是否还会选择extern"C"包裹所有的C++代码。下面我们来看看命名空间如何构建模块化生态~

目录

命名空间介绍

如何声明命名空间

基础命名空间

嵌套命名空间

匿名命名空间

如何使用命名空间

完全限定访问

[using 声明(局部引入)](#using 声明(局部引入))

[using namespace指令(全局引入)](#using namespace指令(全局引入))

回顾整理

标准库的命名空间

[头文件与 std 的关系](#头文件与 std 的关系)

[cout 、cin、 endl 的深度解析](#cout 、cin、 endl 的深度解析)

[(1)std :: cout 表示标准输出流](#(1)std :: cout 表示标准输出流)

[(2)std :: endl 流操纵符](#(2)std :: endl 流操纵符)

[(3)std :: cin 标准输入流](#(3)std :: cin 标准输入流)

常见错误

总结


命名空间介绍

命名是(Namespace)是C++提供的一种代码隔离机制,用于将全局作用域划分为逻辑独立的区域,避免不同模块或库中的同名标识符(变量、函数、类等)发生冲突,一个命名空间就定义了一个新的作用域

例1:A程序员与B程序员现在分模块完成某个工程,A程序员定义了变量tmp ,B程序员也定义了 变量tmp,最后二者模块合并时,可能导致重定义变量报错

例2:C++库中可能定义了某个关键字,但是程序员也可能定义了某个与库中一模一样的变量,这 就无法通过编译

如何声明命名空间

命名空间应该在全局定义,而不是局部

基础命名空间

命名空间使用关键字 namespace 定义,后面跟上命名空间的名字,然后是一对大括号 {},括号的末尾不用加分号,其中包含命名空间的成员。命名空间可以定义变量、函数、子命名空间、类型等

例如小编定义了一个tmp变量:

cpp 复制代码
namespace MyNamespace
{
	int tmp = 0;
}

例如定义函数、变量、结构体:

cpp 复制代码
namespace MyNamespace
{
	//定义变量
	int tmp = 0;

	//定义函数
	int Add(int a, int b)
	{
		return a + b;
	}

	//定义结构体
	struct List
	{
		struct List* next;
		int data;
	};
}
嵌套命名空间

顾名思义,嵌套命名空间就是在基础命名空间里面在定义命名空间,例如:

cpp 复制代码
namespace MyNamespace
{
	//定义变量
	int tmp = 0;

	//定义函数
	int Add(int a, int b)
	{
		return a + b;
	}

	//定义结构体
	struct List
	{
		struct List* next;
		int data;
	};

	//嵌套命名空间
	namespace YourNamespace
	{
		int a = 10;
	}
}
匿名命名空间

顾名思义,匿名就是不去给这个命名空间设置名字,它的作用域仅在当前的编译单元(如:.cpp文件)内可见,例如:

cpp 复制代码
//匿名命名空间
namespace
{
	//定义数组
	int arr[10] = { 0 };
}

如何使用命名空间

完全限定访问

这种是访问类型是限定区域的,现用现拿,方式:空间名+双冒号+空间里面的成员对象

例如:

cpp 复制代码
//完全限定访问
int cur = MyNamespace::Add(5, 5);

嵌套空间的使用也一样:空间名+双冒号 + 使用对象(只不过这里的对象是另一个命名空间)

cpp 复制代码
//完全限定访问
int cur = MyNamespace::YourNamespace::a;
using 声明(局部引入)

相当于在局部告诉编译器,你要在这个局部使用这个空间里的某个对象,它相较于完全限定访问,范围稍微放大了一点,例如:

cpp 复制代码
//using 声明
using MyNamespace::tmp;

//可以直接使用tmp
int cur = tmp;
using namespace指令(全局引入)

这个很危险!属于 全局性的!导入定义的空间,就可以全局直接使用,例如:

cpp 复制代码
//全局导入使用
using namespace MyNamespace;

同样跨文件也是可以的,例如:

回顾整理

首先我们定义了某个命名空间,它的使用是很自由的

你可以选择限定访问,即仅仅对某个对象使用

还可以在某个函数内展开这个空间,那么这个空间仅仅在这个函数内生效

最后是最危险的行为!直接全局展开使用,包括跨文件。这样就无限制了

标准库的命名空间

我们既然可以自己命名空间,C++也有它自己的命名空间,我们称为C++标准库

C -> C++头文件的变化:

早期标准库将所有功能在全局域中实现,声明在 .h 后缀的头文件中,使用时只需包含对应头文即可

后来将其实现在 std 命名空间下,为了和 C 头文件区分,也为了正确使用命名空间, 规定C++头文件不带 .h

cpp 复制代码
// std是C++标准库的命名空间名,C++将标准库的定义实现都放到这个命名空间中
using namespace std;

使用C++标准库进行输入输出:

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

  2. cout 和 cin 是全局的流对象,endl 是特殊的C++符号,表示换行输出,他们都包含在包含

< iostream >头文件中

  1. << 是流插入运算符, >> 是流提取插入符

  2. 使用C++输入输出更方便,不需要像 printf/scanf 输入输出时那样,需要手动控制格式。 C++的 输入输出可以自动识别变量类型,这时候就可以用流提取运算符

  3. 实际上 cout 和 cin 分别是 ostream 和 istream 类型的对象,>>和<<也涉及运算符重载等知识, 这些知识我们我们后续才会学习,所以我们这里只是简单学习他们的使用

头文件与 std 的关系

C++原生头文件<iostream>,所有内容均在 std 内,使用时需要按命名空间使用方法使用std

比如我们使用<iostream>就可以代替原来的C中的各种头文件,例如:

cout 、cin、 endl 的深度解析

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

(1)std :: cout 表示标准输出流

输出通常缓存在内存中,直到遇到换行符**\n** 或者 std::flush 显示刷新

一般搭配 << (流插入运算符)使用,支持链式调用,例如:

cpp 复制代码
//链式输入
std::cout << "tmp:" << 42 << std::endl;
//非链式输入
std::cout << "tmp" << std::endl;

下面两种情况是区别不大的,加了 endl 只是可以换行,刷新c++的缓冲区的内容到文件

(2)std :: endl 流操纵符

它有两个作用:1、插入换行符"\n" 2、强制刷新输出缓冲区,即调用 std :: flush

频繁使用可能导致 I/O 性能下降,建议使用 \n 代替,例如:

(3)std :: cin 标准输入流

功能:从控制台读取用户输入

**>>**是流提取运算符,自动跳过空白字符

C++的输入输出可以自动识别变量类型,这时候就可以用流提取运算符

例如:

当流输入时不要加 std::endl ,可以这么理解:既然需要用户输入,加了endl 结束了还怎么输入?

常见错误

(1)没有用 std ::前缀

(2)随便使用 using namespace std

如果程序员定义了变量 rand ,但是C++标准库中也有对于 rand 的定义,这就导致了冲突报错

(3)输入与输出类型不匹配

总结

(1)std 是标准库的命名空间,任何标准功能都需要通过 std:: 访问

(2)需要清楚 cout、cin、endl、std 命名空间的对象

(3)尽量少用全局的 using namespace std ,使用优先顺序:全限定 -> 局部 -> 全局

【雾非雾】期待与你的下次相遇!

相关推荐
小王努力学编程20 分钟前
高并发内存池(二):项目的整体框架以及Thread_Cache的结构设计
开发语言·c++·学习·算法
old_power35 分钟前
C++使用PoDoFo库处理PDF文件
c++·pdf
虾球xz40 分钟前
游戏引擎学习第266天:添加顶部时钟概览视图。
数据库·c++·学习·游戏引擎
梁小憨憨1 小时前
循环卷积(Circular Convolutions)
人工智能·笔记·深度学习·机器学习
码出钞能力1 小时前
对golang中CSP的理解
开发语言·后端·golang
Lester_11011 小时前
嵌入式学习笔记 - 关于单片机的位数
笔记·单片机·学习
金融数据出海1 小时前
黄金、碳排放期货市场API接口文档
java·开发语言·spring boot·后端·金融·区块链
keepDXRcuriosity1 小时前
分治算法详解及 C/C++ 示例
c语言·c++·排序算法
菜一头包1 小时前
Lua学习笔记
笔记·学习·lua
dot to one1 小时前
C++ 渗透 数据结构中的二叉搜索树
数据结构·c++·算法·visual studio