目录
一,多态的概念
多态是什么?多态的字面意思就是多种状态!!!也就是当不同的人在做同一件事情的时候会呈现出不同的状态。比如以下例子:
在这里我定义了两个对象,分别是Teacher和Student。其中Student继承于Teacher。在这两个子类里面都有一个方法叫做eat()。在定义完以后,我们便开始定义对象T和S。然后再来调用Func()函数。在这里运行便可以看到结果如下:
可以看到,对于不同的对象这里便实现了多态多态调用。
二,多态的条件
首先,我们要构成多态的条件之一便是这两个类具有父子类关系,并且得用父类指针或者引用调用。
例如:
当我的func()内的参数类型为父类的指针或者引用时:
如果不是父类的指针或者引用:
如果不是父子类关系:
在这个条件以后我们要找的便是三同:
1.函数名相同。
2.返回值相同。(除了构成协变,构成协变的条件是父子类的方法的返回值是父子类的指针或者引用,派生类的方法的返回值是派生类的指针或者引用)
协变:
3.父类中的方法必须是虚函数(子类中可以不加,但是建议都加上)
总结:
构成多态的条件:两个类具有父子关系,使用父类指针或者引用调用方法,父类的方法必须是虚函数,两个类里面的方法必须是函数名相同,参数相同,返回值相同(除了构成协变)。
三,final和override
1.final
final关键字是C++11中加入的一个新语法。被final修饰的类不能被继承,被final修饰的虚函数不能被重写。例如:
1.类被final修饰
2.虚函数被final修饰
2.override
override关键字也是C++中加入的一个新语法。它的作用是帮助用户检查虚函数是否被重写。如果没有被重写便报错:
如:
四,抽象类
1.纯虚函数
纯虚函数也是C++里的一个语法。语法如下:
现在我这个eat()便是一个纯虚函数。
2.抽象类
啥是抽象类呢?抽象类便是一个含有纯虚函数方法的一个类,如下:
我的类Person便是一个抽象类,因为我的Person类里面含有一个纯虚函数eat()。
在这里要注意一下抽象类的一些性质:
1.抽象类不能实例化一个对象,比如我用Person来初始化一个对象便会报错:
2.抽象类在经过派生类重写以后才可以来实例化一个对象
1.未重写
2.重写后:
五,多态的原理
1.探索
我们为什么能够实现多态呢?首先来看看看看一个实现了多态的对象那个的大小有多大,该对象如下:
这个对象有多大呢?如果没有这里的多态的话这个类的大小其实是4个字节大小的,但是使用了多态以后该类的大小便成了八个字节大小:
那这多出来的四个字节从何而来呢?先来打开我们的监视窗口看看:
会发现我们的Student对象里面会多一个叫做_vptr的东西。那普通对象有吗?
现在我将Student的继承关系去掉:
对于同一段函数,不具有继承关系的类的大小便是4。再来打开监视窗口看看:
会发现我们的s里面没有那个_vptr。那说明,我们多出来的4个字节的大小便是_vptr的大小喽。
2._vptr是什么?
_vptr是个啥呢?其实它就是个虚表指针。在这个_vptr里面存的便是我们的虚函数的地址。我们的子类或者父类对象便是通过这个虚表指针来找到相应的函数然后进行call虚表函数里面存放的地址跳转到某一个函数里头进而实现函数体里面相应的功能的。
1.注意点:
1.同一个类实例化的对象里面存放的虚表指针是一样的。
2.不同的类不管虚函数是否被重写,我们的虚表指针都是不一样的。