本期开始我们来对C++进行学习
目录
1.C++关键字
2.命名空间
3.C++的输入与输出
C++总计63个关键字,C语言32个关键字
asm | do | if | return | try | continue |
auto | double | inline | short | typedef | for |
bool | dynamic_cast | int | signed | typeid | public |
break | else | long | sizeof | typename | throw |
case | enum | mutable | static | union | wchar_t |
catch | explicit | namespace | static_cast | unsigned | default |
char | export | new | struct | using | friend |
class | extern | operator | switch | virtual | register |
const | false | private | template | void | true |
const_cast | float | protected | this | volatile | while |
delete | goto | reinterpret_cast |
我们并不需要刻意的去记住这些关键字,在后续使用中我们就会慢慢熟悉他们
在C/C++中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染,namespace关键字的出现就是针对这种问题的
#include
#include
int rand = 10;
int main() {
printf("%d\n", rand);
return 0;
}
我们在编译这一段代码时,会出现错误,在C语言中,并不会出现这种错误,但是在C++中却会报错
我们来看这段错误,是重定义,即我们定义的rand和库中的一个rand函数冲突,所以在C语言中,是存在命名冲突的
命名冲突主要包含两方面,一方面是我们和库冲突,所以在使用C语言写一些大型项目时会出现这样的问题,在我们引入某个库后会出现一堆报错,因为我们定义的变量或者函数和库里的冲突了,另一方面是我们互相之间冲突,比如两个人写一个项目,一个人定义了一个了一个变量a,另一个人也定义了一个变量a,最后两个代码是会合并的,而合并时就会出现冲突,此时就需要一个人来改变变量名,如果将这个变量使用了成百上千遍,那就非常麻烦了
为了解决这个问题,C++引入了命名空间
我们在网络上看C++代码时,经常能看到这样一段代码
#include
using namespace std;
第二行的代码是什么意思呢?我们先将这个问题保留,一会回过头来看
为了使程序不冲突,我们使用域来进行隔离
#include
#include
//域
namespace hello {
int rand = 10;
}
int main() {
printf("%d\n", rand);
return 0;
}
我们先看这段代码
#include
#include
int a = 0;
int main() {
int a = 10;
printf("%d", a);
return 0;
}
我们知道,这两个a是可以同时存在的,main函数里的a是局部变量,也就是在局部域,而外部的a是全局变量,也就是在全局域,我们知道,运行这段代码,会输出10
如果我们想要访问全局的a,该如何访问呢?
在C++里,我们可以使用::来进行访问,:: 叫做域作用限定符,局部域和全局域,是优先在局部搜索,没有局部才在全局搜索,::的左边什么也没有(加上空白是为了好看)
我们再看这样一段代码
#include
#include
int a = 0;
namespace hello {
int a = 10;
}
int main() {
int a = 20;
return 0;
}
这3个a我们该如何访问呢?
如果我们直接进行访问,访问的是局部的a
如果局部不存在,接下面就是全局搜索了 ,而命名空间域里的变量,不指定是不会去搜索的
如果想要访问命名空间域,有两种操作,一种是展开命名空间域,另一种是指定访问命名空间域
所以using namespace是展开命名空间域,此时我们回过头来看using namespace std;
这段代码的意思就是展开命名空间域,而这个std是标准库的命名空间
这个操作就是指定访问命名空间域,::前面什么都不加,就是访问全局域
我们再看这种情况,展开的本意就是暴露到全局,所以是会报错的
此时就不知道你需要访问哪一个了
所以我们不要轻易展开命名空间,展开是编译时是否去命名空间中搜索,没有展开就不会去搜索
我们再回过头来解决rand的问题,我们只需指定访问即可解决
命名空间除了定义变量,还可以定义函数,定义类型,唯一要注意的是命名空间最后的 } 后是没有 ; 的
命名空间也是可以嵌套的
namespace n1
{
int a = 10;;
int b;
int add(int left, int right)
{
return left + right;
}
namespace n2
{
int a = 20;
int c;
int d;
int sub(int left, int right)
{
return left - right;
}
}
}
命名空间过大时,为了防止冲突时就需要使用嵌套分割
多个同名的命名空间是会被合并的
这里我定义了两个头文件
在每个头文件里都定义了hello的命名空间
我们在test.c里可以对这三个命名空间里数据进行访问,这三个命名空间合并成了一个命名空间
C++里有STL库,每个库都有命名空间,最后也合并在一起,就是这样使用的
下面,我们回过头来看这句代码
#include
我们发现c语言的头文件都是xxx.h,而c++不是.h,为什么呢?
其实在早年的时候,是有#include
C++的iostream库里有一个cout,这个类似C里面的printf,但是我们发现这里报错了,原因就是我们上面说的,如果我们不指定访问或者展开命名空间,就不会去主动搜索
我们的一种解决办法为让他直接去命名空间搜索
第二种办法就是我们展开命名空间
另外,我们展开不展开都是可以加std::的,一般是推荐使用第一种方法
我们展开的话是要去std里搜索,但前提是上面有std,如果没有的话也是不行的 ,不加是不会搜索的
但是用using namespace std;全部展开是有风险的,如果我们和库有冲突,就会报错
所以我们建议项目里面不要展开,在项目里我们用指定访问,不要轻易展开
我们使用这种办法,展开常用的即可
我们在上面使用了cout,这是一个全局对象
我们发现cout << "hello " << endl;
<<在C里面叫做移位运算符,在C++里叫做流插入运算符,并且可以支持多个值输出
我们输出了字符串hello world,输出了10,\n是换行,endl也是换行,endl也是全局的
cout相比于printf,真的强大的地方在于自动识别类型,我们使用printf需要指定%d,%f等等,而cout不需要指定类型
既然有cout,与之对应的还有cin,这个类似scanf
>>叫做流提取运算符
这几个可以混着用,大家怎么舒服怎么来就行
以上即为本期全部内容,希望大家可以有所收获
如有错误,还请指正