引言:
北京时间 2023/2/1/20:38,三天没写博客,打字量严重下滑,这两天是看剧时间,我发现看电视剧有时候还是非常的让人无法自拔的,一天追完一部30集的电视剧,我还是很佩服我自己的,现在我们把电视剧看完了,并且并没有发现什么更好看的电视剧,并且这两天要开始上课了,所以我们要开始日更博客啦!我们要开始学习我的的C++了,刚开始我们学习的就是一些的入门基础,但是网上都说学好C++是非常困难的,当然我对这点是深信不疑的,反而是因为C++非常的不好学,我反而是对其非常的感兴趣,想着不就是一门语言吗?不就是一些指令吗?到底为什么难?难在什么地方?也许这就是无知的我们现在的想法,反正我不知道C++为什么难,不就是在C语言的基础上加了一些东西吗?所以在我们没有学习过一个东西的情况下,也就是无知的情况下,任何东西理解起来都是没有想象中的那么难的感觉,但是我知道这是因为我的无知,因为只有当你开始了解一个东西的时候,你才会发现自己的无知?而不是天真。有一句话说的好,了解的月多的人,反而是越觉得自己无知,写到这里,很多学习计算机的同学可以说都和我一样都有一个想法,就是早知道不选这个专业了,这样我们就不需要学这么多的东西了,这样我们就可以比较轻松,因为我发现学计算机真的需要掌握很多东西。所以今天我们就开始掌握一项新的技能,虽然我们学习过C语言,但是我相信C++给我们带来的挑战会远远的超过C语言,所以我们今天就开始学习我们的C++吧!让我们从基础语法出发,让我们以后可以熟练掌握C++基本语法,逐渐遨游在C++编程之中。
必看的C++书籍
学习C++需要看的书籍,当然这个是在我们掌握好C++的语法之后干的事情,自己看书来进一步印证我们的知识掌握的正确性和熟练度。目前我也还没有这些书,希望以后的我在看到此文的时候已经拥有了这些书吧!
看书学习知识的过程很重要,但是做题的过程更加重要,所以我们一定要多花时间去做题,不要怕了这个过程,因为每个相当程序员的人都必须经历这个过程,希望以后我那天看见这段话的时候,已经对做题有了一定的自己的理解了吧!不像是现在,对做题一点感觉都没有。心里作用,不能害怕做题!
C++基础语法
首先语法原理和C语言还是差不多的,基本格式和C语言是也差不多,谁让我们的C++包含了C语言中的所有内容呢?所以本质上C++语言就是在C语言的基础上进行各种各样的功能的添加和功能的更替,使C语言在使用上更加的优异,从而诞生的一门新语言,并且我们从C++的基本代码格式可以发现,头文件,主函数之类的东西都是一样的,但是此时却在头文件的下方多了一个东西,using namespace std;
这个是什么意思呢?所以接下来我们就来探讨一下C++中的这句代码的意思和为什么C++中要添加这条代码,而C语言中却不要。
命名空间
上述我们说过,我们的C++就是在C语言的基础之上进行改进和添加。所以命名空间的概念就是为了该进C语言中的一些问题的,问题:C语言中不可以在相同区域定义相同的变量、定义变量时,有和C库中的变量相同的风险和不同文件合并到同一文件时变量有相同的风险,所以此时我们就带着这些问题,也就是C语言的小缺陷,我们来理解什么是命名空间,但是我们理解命名空间前,我们先复习一下C语言中的局部变量和全局变量的区别和概念。
全局变量 | C语言中的全局变量就是函数以外的变量和静态变量,均是保存在全局存储区中,占用永久性的存储单元,并且生命周期就是整个工程 |
---|---|
局部变量 | 局部变量,即自动变量,各种函数中的变量,保存在栈中,只有在所在函数被调用时才由系统动态在栈中分配临时性的存储单元,并且生命周期只在该函数范围内,出了函数生命周期随着栈的销毁而结束 。 |
问题1:C语言中不可以在相同区域定义相同的变量
此时我们搞清楚了局部变量和全局变量的大致情况,我们现在就通过局部变量优先的原则,我们引出一个C++中的符号(::),域作用限定符。
问题:我们如何做到函数中优先打印全局变量,而不打印局部变量,此时若想实现这一想法,就涉及到我们的域作用限定符,如下代码:
此时可以发现我可以通过域作用限定符来让全局变量优先,打印全局变量,原因就是:我的域作用限定符可以让我的printf函数此时不从函数内寻找a变量,而是从函数外去找a变量,如果外部有变量a就打印外部的变量a,无再打印函数内部的a变量。
总:所以我们此时发现,在相同的区域中我们不可以使用同一个变量,但是在不同的区域(函数内外,函数类别),我们是可以使用同一个变量的
问题2:定义变量时,有和C库中的变量相同的风险
如下代码:
因为我们的C库中有一个生成随机数的rand函数,所以此时我们如果用rand来当变量的话,就会有如上图的问题。
总:我们就可以把我们的C库函数全部代码给放到一个自己的命名空间中,封装起来,从而就构建成了我们的标准命名空间using namespace std;
问题3:不同文件合并到同一文件时变量有相同的风险
此时我们知道了在不同的区域我们是可以使用同一个变量的,并且我们可以想到,当我们在写某些工程的时候,我们的代码是写在不同的文件之中的,并且我们的不同文件在最后是需要整合到同一个文件的,所以此时当我们在整合文件的时候,就会导致不同的文件合并的时候变量有相同的可能,所以此时我们为了解决这个问题,此时我们就引出了我们的命名空间的概念,来为我们防止这种情况的发生。并且使用命名空间的概念,我们也可以很好的解决上述的两个问题。
命名空间概念:创建一个命名空间域,不改变声明周期,只改变使用。
命名空间原理:创建出一个命名空间域,无论是不同文件的代码,还是同一文件的不同区域中的代码,还是各种C库中的代码,我们都放到我们的各自的命名空间中(例:namespace std、namespace wwx、namespace a
),这样,我们在不同的命名空间中创建相同的变量,并且根据可以在不同的区域使用相同的变量原理,我们就可以让我们的变量重定义问题得到很好的解决。
并且此时我们的命名空间是支持套娃使用的,按照原理,一直嵌套我们的命名空间。
如图:
就是在我们的命名空间namespace A
中再创建命名空间,从而实现不断的嵌套,从而实现各个变量一直保持在不同的区域之中,从而解决重命名问题。
并且此时的在不同命名空间中访问相同名字的变量的方法,如下图所示:一共有三种方法
1.指定从命名空间中找
2.全部展开
此时的using namespace std
代表的就是将我们的C库给我们全部展开,此时就等于是没有对C库中的函数的变量命名做命名空间的使用。
3.部分展开,把常用的展开,不常用的指定
这样我们就可以准确的拿到每一个相同名字的变量了。
总:命名空间就是使用了可以在不同的区域使用相同的变量原理,并且此时就是把每一个命名空间给看出是一个一个的函数,在这些不同的函数中,我们各个函数(命名空间)互不干扰,从而实现命名自由的问题。
C++输入和输出
目前以我们的所学,我们还不能很好的把cout和cin给搞明白是什么,所以我们目前只要会使用cout和cin就行了,具体使用规则入下图:
并且涉及两个符号<<
(流输入)和>>
(流输出)
看不懂不怕,我们就当做是C语言中的printf和scanf使用就行了,并且把cout理解成我们的控制台(黑屏),<<理解成我要打印的数据流入黑屏的意思,cin理解成我们的键盘,数据从键盘上进过流输出流到我们的屏幕上。
基本使用语法:
cout<<表达式1<<表达式2<<表达式3...<<表达式n;
cin>>变量1>>变量2>>变量3>>.....>>变量n;
特点:可以自动识别类型
什么是缺省参数
还是那个道理,我们的C++就是为了改善一些C语言在某些语法方面上的不足而出现的语言,所以缺省参数概念的提出也就是为了要改进C语言在某些方面使用起来不怎么方便的问题。缺省参数顾名思义就是有关参数的使用这一方面的问题,当然在我们的代码中也就是和我们的传参有关的问题,并且作用就是我们在进行参数的传递时,我们不仅可以给定一个实参,并且将实参传递到某些函数的形参中,而且也可以在函数的形参给定一个值,当我传递参数的时候,如果有实参,我们的函数就照样接收我们的实参,如果没有实参,它也不会报错,就是就默认我们的实参就是形参的赋值,也就是我们的缺省参数。所以结合上述文字,看下面的代码,让我们彻底搞懂什么是缺省参数。
如图:
按照上述的文字描述,我相信我们可以轻松的看懂并且对缺省参数有更深一步的认识,此时我们就把上述图中的函数称为全缺省参数函数void Function(int a = 10,int b = 20,int c = 30)
。并且如果此时该函数中的参数只有一个或者两个赋值(但是只能从第一个参数位置开始缺省),我们就把其称为半缺省参数函数,如果该函数中都没有赋值,我们就把其称为普通函数,该函数就不是我们的缺省参数了。
使用缺省参数解决问题的场景
文字描述:当我们写了一个栈,我们要往这个栈中添加数据,但是此时我并不知道我有几个数据。按照我们在数据结构中学习栈的时候,我们知道为了避免空间的不足和浪费,我们使用的是空间扩容的方法来解决,但是可以发现,空间扩容的方法在我不知道有几个数据的时候是很好用的,因为它会根据空间的大小一直进行扩容,扩到把我的数据存储完为止,但是当我知道我要添加的数据个数的时候,再按这种扩容的方式,就会感到不足(扩容存在消耗),所以此时我们的缺省参数就可以很好的帮我们解决这种问题。
如图:
此时我们缺省参数的作用就展现的淋淋尽致了。
总:只有函数中参数有被赋值的才叫做缺省参数,并且我们的缺省参数不能同时在声明和定义出现,通常在声明的时候定义缺省参数。
如何理解函数重载
学习了上述知识我们解决了变量命名冲突的问题,此时就让我们来看一下什么是函数重载吧!其实函数重载的本质也就是为了帮我们解决函数名重命名的问题,变量重命名可以通过命名空间利用不同区域可以使用相同变量原理解决,那么我们的函数重命名用什么解决呢?此时就涉及到了我们的函数重载,函数重载:原理就是将该函数的特征拿出来比较分析,得出每个函数除了函数名之外,还有参数方面可以用来区分这个函数,所以我们把参数这个特征也给加到识别函数中去,从C语言中的只区别唯一特征函数名,到可以区别函数的所有特征(函数名加参数),实现我们的函数名重命名问题,这也就是我们的函数重载了。
如下代码:图一属于函数重载,图二并不属于
此时根据图示我们发现使用函数重载可以相同的函数名中,实现不同的代码,原理就是把函数的参数变成了函数的特征之一。
所以根据这个原理,此时我们可以得到一个结论,只要函数名相同但参数类型不同或者参数个数不同,或者参数的类型的顺序不同就都属于我们的函数重载,本质原理:就是在我们的汇编过程,我们会对函数进行一定的函数特征(函数名+参数)进行修饰,将同一函数名,但参数不同的函数,修饰成一个唯一的汇编语言,这样我们在汇编过程中,使我们的电脑也可以识别出这些函数的特征,从而区别这些函数。例下图:
此时我们的Function
函数就被修饰成了上图_Z8Functionii
的形式了
总:通过给函数增加参数的特征,此时我们就可以很好的解决函数命名冲突的问题
C++中理解引用
还是那句话,我们的C++就是为了补充一些C语言中的不足的,所以此时我们的引用的概念的提出也就是为了补足C语言中的一些缺陷,并且此时的这个缺陷是大家都比较害怕的,就是有关的指针问题,为了弱化指针,我们的C++中就提出了引用的概念,使用引用我们就可以替代一部分的指针的使用场景,从而使我们对指针的使用变得有选择甚至替代指针的使用,从而实现我们编码更加的灵活和方便,所以什么是引用呢?其实引用就像是我们日常生活中的小名,外号的意思,也就是一个人(一块空间)可以有两个名字。所以我们的引用就是对一个人(一块空间),进行取别名而已。
具体代码如图:
此时我们根据上图所示,我们发现,我们的int& k = i
就是我们的一个取别名(引用)的操作,这样此时i变量就有了第二个名字k了,所以我们的符号&不仅有去地址的作用,在学习过C++之后,我们知道&还有引用的作用,使用&引用之后,就可以给一个变量取别名了,并且根据地址的打印我们发现,取别名k之后,它的地址还是跟 i 是同一个地址,进行引用操作后i和k是共用同一个内存空间的。当我们没有使用&引用符号的时候,int j = i;
该操作就是普通的复制操作,并不是引用操作,此时i和j是两块不用的空间,所以有两个不一样的空间地址。还发现,根据同一块空间的原理,我们修改k(修改别名)就是在修改它本身,所以改k等于改i,改j不等于改i。
区分,此时按照上述的理解,我们是把引用之后的变量理解成是和原变量共同空间的,但是注意我们在底层的系统调用的时候,我们实现引用这个原理的时候,我们的底层代码用的本质上其实还是指针的概念,指针的概念理解,我们其实还是开辟了一个新的指针空间,所以本质上,在底层我们的引用变量和变量之间不是共用同一块空间的。
引用代替指针的一些骚操作
学了c++中的引用的概念,此时我们就可以实现,不使用地址和指针实现两个数的交换,原理就是给要交换的变量给取一个新的名字,然后交换这个新的名字
可以看出我们在第二个Swap代码中,我们使用了引用的方法,此时理解就不能像第一个Swap代码一样理解,形参是实参的地址,并更不能理解成形参是实参的拷贝了,此时我们就要理解成形参是实参的引用(形参是实参的别名),这样根据上述所说,改变别名就是改变自己的原理,此时我们就很好的把我们的参数通过取别名的方式传递到了我们的函数当中,这样我们就可以实现不使用地址的方式也可以很好的使用我的实参变量。
指针的引用,同理如下图:
此时意思是,把p这块空间通过(int*&)给int取别名的方式和p共享空间,所以此时就可以理解成(int&和int&)就是给int和int*取别名的意思。所以我们可以给任何类型取别名。
一级指针的引用
二级指针的引用
总:引用的好处就是在我们的形参和实参的传递的时候的使用过程变得更加的简单(使形参和实参的关系变得更加的不重要),实现直接改实参的名字(把形参和实参的一些关系给忽略掉),我就是我,不是拷贝也不是地址,本人说了算,不需要额外操作。
剩下的有关C++的基础语法,我们下一篇博客更新啦!