C++学习
C++学习第一课:C++学习须知
C++学习第二课:命名空间域
文章目录
前言
本篇文章为正式学习C++的第一节课,主要篇幅介绍命名空间域namespace的相关内容,并对涉猎知识作出补充介绍
一、C语言的第一个问题:命名冲突
1. 冲突的各种情况
(1)我们写的和库里的关键字冲突
(2)不同人写的模块合并之后相互冲突
冲突举例
#include <stdio.h>
#include <stdlib.h>
int rand = 10;
// 这里由于stdlib库中含有rand关键字。因此再次定义将会产生冲突
int main()
{
printf("%d\n", rand);
return 0;
}
// 编译后后报错:error C2365: “rand”: 重定义;以前的定义是“函数”`
2. 冲突的解决方法
(1)C++学习的第一个关键字:namespace
(2)namespace的类型:
A. 官方命名空间域
B. 自定义命名空间域
命名空间内可以定义各种东西,包括变量、函数、结构体甚至嵌套命名空间
namespace zzw
{
// 命名空间中可以定义变量/函数/类型
int rand = 10;
int Add(int left, int right)
{
return left + right;
}
struct Node
{
struct Node* next;
int val;
};
}
(3)namespace的访问
方法一:使用using将命名空间中的某个成员引入
using N::b;
int main()
{
printf("%d\n", N::a);
printf("%d\n", b);
return 0;
}
方法二:使用using namesapce将命名空间引入
using namespce N;
int main()
{
printf("%d\n", N::a);
printf("%d\n", b);
Add(10, 20);
return 0;
}
方法三:使用命名空间名称及作用域限定符
int main()
{
printf("%d\n", N::a);
return 0;
}
注一:头文件是将头文件中的内容cv到代码中,而命名空间域的展开是允许进入搜索,两者并不等同
注二:命名空间只可在全局域中展开,不能在局部展开
3. 域的相关知识补充
(1)域的种类
A. 命门空间域namespace
B. 类域
C. 局部域
D. 全局域
(2)不同的域可以定义同一个变量
示例代码如下
#include <stdio.h>
int a = 10;
int main()
{
int a = 0;
printf("%d\n", a);
return 0;
}
(3)变量在多个域中的访问规则
A. 局部域优先,全局域次之
如何跳过局部域直接访问全局域
#include <stdio.h>
int a = 10;
int main()
{
int a = 0;
printf("%d\n", ::a);
return 0;
}
B. 命名空间域没有展开或者指定访问是不会进行搜索的
问:展开命名空间之后,全局和命名空间谁被访问
答:展开命名空间可以理解为把空间内部的东西放到全局中(虽然我们知道本质只是允许进入搜索),因此展开之后会突然变量冲突而报错
4. 学成归来:解决一开始的冲突问题
#include <stdio.h>
#include <stdlib.h>
namespace zzw
{
int rand = 10;
}
int main()
{
printf("%d\n", zzw::rand);
return 0;
}
问:我直接在局部定义一个rand不就好了吗
答:那样就变成局部变量了,有违初衷
二、命名空间的嵌套
1. 为什么需要嵌套
答:域太大自身也容易冲突,因此进行“分装”
嵌套代码示例
namespace N1
{
int a;
int b;
int Add(int left, int right)
{
return left + right;
}
namespace N2
{
int c;
int d;
int Sub(int left, int right)
{
return left - right;
}
}
}
2. 嵌套之后如何访问
namespace N1
{
int a = 1;
namespace N2
{
int a = 0;
}
}
int main
{
printf("%d\n"N1::N2::a);
}
3. 多个同名的命名空间会被合并
问:合并之后要是变量冲突了怎么办
答:再定义一个空间域进行嵌套即可
三、基于命名空间浅谈输入输出
1. std是什么?
答:std是C++标准库的命名空间名,C++将标准库的定义实现都放到这个命名空间中
2. 为什么代码中常常出现std的展开
答:因为cout、cin、endl等关键字在std域中
#include<iostream>
//使用cout标准输出对象(控制台)和cin标准输入对象(键盘)时,必须包含< iostream >头文件,以及按命名空间使用方法使用std。
using namespace std;
int main()
{
cout<<"Hello world!!!"<<endl;
return 0;
}
注:实际上cout和cin分别是ostream和istream类型的对象,>>和<<也涉及运算符重载等知识,这些知识我们我们后续才会学习
注:早期标准库将所有功能在全局域中实现,声明在.h后缀的头文件中,使用时只需包含对应头文件即可,后来将其实现在std命名空间下,为了和C头文件区分,也为了正确使用命名空间,规定C++头文件不带.h
3. 比展开std更好的选择?
A. 为什么直接展开不好
答:展开有风险,容易冲突报错,当然平时直接展开也不会有问题
B. 更好的选择:指定访问
using std::cout
四、输入输出
1. <<和>>
答: <<是流插入运算符,>>是流提取运算符
2. cout 、cin和 endl
答:cout和cin是全局的流对象,endl是特殊的C++符号,表示换行输出,他们都包含在包含< iostream >头文件中。
3. cout与printf
A. cout的好处:可以自动识别类型
B. cout的坏处:精度调节异常麻烦
注:c++可以兼容c,因此需要精度调节可以直接使用printf
问:printf的输出比printf快?
答:正确的,因为c++兼容c
注意:c++对于c的兼容可以关闭,以此提速
总结
本节课主要对命名空间域namespace的使用做出了较为完整的说明,并涉猎了一点输出输入的内容,这方面会在后面做更详细的介绍