C++基础知识总结
个人理解,对于c++的学习,就是c语言的延续,甚至可以说,c++包含了c语言,c语言的绝大多数都能被c++兼容。但是,本质的用处还是有些许区别的,c语言,主要面向的是过程,注重的是对于过程中每一步的操作,声明,以及顺序,这些步骤。而c++面向的是对象,(对象可以理解为对于我们现实生活的一种抽象,比如,人是对象,物品是对象),注重的是对于一种整体上的一种把控,对于整体上的操作与声明,强调对象各自需要做些什么事情,然后在分别进行实现。
遇到了大佬讲的一个很好的例子:
面向过程:1.人把脏衣服脱掉 2.人打开洗衣机 3.洗衣机开始洗衣服 4.洗衣机甩干 5.人晾衣服
面向对象:有两个对象,一个对象是人,功能有脱掉脏衣服,打开洗衣机,晾衣服
一个对象是洗衣机,功能有洗衣服,甩干
对于c++,我就从写程序一开始我遇到的困惑的知识点开始吧。(由于c++是c语言的延续,c++前面的知识基本上就是c语言,所以这篇文章就有c基础之上学c++)
1、namespace
namespace叫做名字空间或者命名空间。比如我们会这样写std::cin,就是调用std命名空间内的cin这个函数。双冒号前表示命名空间,后表示命名空间下的函数。
作用:为了解决名称冲突,因为,在项目中函数名、全局变量、结构、联合、枚举、类,非常有可能发生名字冲突,而名字空间就对这些命名进行逻辑空间划分,来解决名称冲突问题。
2、开辟空间上
相对于c的malloc和free,c++一般用得是new 和delete,后者是前者的封装。这里需要主要的是new和delete都是运算符,而不是库函数,所以我们可以直接用。
用法:1、申请空间 int* ptr = new int; 2、申请连续的空间 int* arr = new int[10];
1、释放空间 delete ptr; 2、释放连续的多个空间 delete[] arr;
3、重载
重载可以分为两种,一种是函数重载,一种是运算符重载。
函数重载
具有相同的名称,执行基本相同的操作,但是使用不同的参数列表。参数列表就是参数的多少和类型。这样一来减少了我们函数名的数量,增加了代码的可读性,有助于理解和调试代码。
例如:
void swap1(int *a, int *b); //交换 int 变量的值
void swap2(float *a, float *b); //交换 float 变量的值
void swap3(char *a, char *b); //交换 char 变量的值
void swap4(bool *a, bool *b); //交换 bool 变量的值
像这样,我们可以用函数重载,将swap全部重载为一个,只要我们传入的函数类型不同,就会分别执行对于的函数操作了。
运算符重载
对于我们的基本的运算符,加减乘除,一般上只能对比如整形,浮点,字符类型进行加减乘除,对于,比如,两个类之间如何进行加减乘除就不能进行了。这时就产生了运算符重载,通过写运算符重载,规定两个类之间的运算,比如+,-,来执行我们的操作。
4、引用
符号:&;
引用的用处就是取别名,,对引用的操作与对变量直接操作完全一样,有点像我们指针的实体化。
比如,int a =10; int &b =a; 也就是这这片存有10的空间,以前叫a,a里面存放着10,通过引用之后,这个地方又叫b了。b就是a的意思,我们对b进行修改,也就是对a进行修改。
对于引用需要注意的地方:
1、创建引用的同时必须将其初始化。
2、引用不能为NULL,其必须与某个标识符关联。
3、引用被初始化之后就不能再更改引用关系
4、一个变量可以有多个引用。
5、构造函数与析构函数
析构函数和构造函数都是必须执行的,如果我们不自己提供,那么编译器会自动执行一个空的析构和构造函数
构造函数:
作用:为所有成员属性初始化,处理对象的初始化。
特点:
1、函数名与类名相同。
2、没有函数返回值不用写void.
3、自动调用,并且只调用一次。
4、可以有参数,可以发生重载。
析构函数:
**作用:执行对象的清理工作,当对象的生命周期结束的时候,会自动的调用。**析构函数除了释放工作,还可以做一些用户希望它做的一些工作,比如输出一些信息。
特点:
1.析构函数没有返回值,没有参数;
2.函数名与类名相同。
3、没有参数,所以不能重载,一个类仅有一个析构函数;
4、自动调用,并且只调用一次。
6、类和对象
class就是我们的类,对于类,如果学过c语言,其实类就是c中结构体的升级版,在某种意义上,基本可以混为一谈。
封装
对于c语言中与类最像的结构体来说,结构体只有属性,没有操作,而我们class就是将属性和行为封装在了一起。打个比方,对象是一个人,结构体里面有声明的是,这个人有两支手,两条腿,对于class来说,不仅声明了这个人有两支手,两条腿,还说了,这个人用两支手拿东西,用两条腿走路。将属性和操作放在一个类下,这个操作就是封装。
class有三种权限,public(公共);protected(保护);private(私有):
- public:可以被该类中的函数、子类的函数、友元函数访问,也可以由该类的对象访问;
- protected:可以被该类中的函数、子类的函数、友元函数访问,但不可以由该类的对象访问;
- private:可以被该类中的函数、友元函数访问,但不可以由子类的函数、该类的对象、访问。
对于权限之上,结构体和类之间的区别
class的默认权限是私有权限,而struct的默认权限却是公共权限。
继承
继承机制主要是用于面向对象程序设计,使代码可以复用,它允许程序员在保持原有类特性的基础上进行扩展,增加功能。这样产生的新类,称派生类(或子类),被继承的类称基类(或父类)
打个比方来说,在我们生活中,有猫这个类,猫中,可以分为加菲猫,波斯猫,折耳猫,暹罗猫,等等。可以知道,在猫这个大类中,许多小类的猫,都有着猫的共同点,相当于说,在满足猫这个大类之下,再分小类的猫。而继承,就是我们写了一个猫,然后我们在写小类的猫的时候,我们就继承猫这个大类,猫这个大类的属性就给我们小类猫class上,这样我们只需要写,这个小类的猫的特点就行了。
继承权限问题
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JzAsjPlt-1680655398140)(C++%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86%E6%80%BB%E7%BB%93%20e49b824901064da79c046d4893d94b75/Untitled.png)]
不可见的意思就是不能继承,private就是私有财产,不能够被继承下去。
继承中析构函数和构造函数执行的问题
对于构造函数:编译器会默认先调用父类的构造函数,再调用子类的构造函数
对于析构:析构函数和构造函数相反,编译器默认先调用子类的析构函数,再调用父类的析构函数。
多态
“多态(英语:polymorphism),是指计算机程序运行时,相同的消息可能会送给多个不同的类别之对象,而系统可依据对象所属类别,引发对应类别的方法,而有不同的行为
打个比方来说:对于人这个对象来说,在不同时候,我们有着不同的情绪,开心,伤心,等等,一个人多种情绪,有着多种状态。
写的情况:在父类中声明了要做什么?没有写具体的实现,当子类继承父类之后,将要做什么进行实现。比如,写一个猫的类,假设有两个猫的子类,一个为狸花猫,一个是纯白猫。在猫这个大类中,猫都是有毛的,但是没有具体说到底是什么毛,当我们的子类继承了猫这个大类后,就会写具体这个猫的毛是什么,一个是狸花,一个是纯白。因此这个毛,就在众多子类中有了多种状态(狸花,纯白),从而形成了多态。
多态的条件:
1 、必须通过基类的指针或者引用调用虚函数。
2、 被调用的函数是虚函数,且必须完成对基类虚函数的重写。
虚函数
什么是虚函数?
- 虚函数,在类成员方法的声明(不是定义)语句前加“virtual”, 如 virtual void func()
- 纯虚函数,在虚函数后加“=0”,如 virtual void func()=0
虚函数的实现是由两个部分组成的,虚函数指针与虚函数表。
虚函数存在哪里?
虚函数是带有virtual的函数,虚函数表是存放虚函数地址的指针数组,虚函数表指针指向这个数组。对象中存的是虚函数指针,不是虚函数表。
虚函数存在哪里?
存在代码段。
虚函数表存在哪里呢?
虚函数表放在了全局数据段。
好处:C++中一个类是公用一张虚函数表的,基类有基类的虚函数表,子类是子类的虚函数表,这极大的节省了内存
对于虚函数与纯虚函数的区别:
子类如果不提供虚函数的实现,那就会自动调用父类的缺省方案(由编译器自动处理)。而子类如果不提供纯虚函数的实现,则编译将会失败。对于纯虚函数,父类提供的是纯虚函数抽象版本,而子类提供纯虚函数的具体实现的版本。