【C++面向对象之继承、多态与虚函数-哔哩哔哩】 https://b23.tv/ZK46C3L
虚函数用来实现多态

如图所示,dog和cat均继承自animal类。我们希望每个子类型都有work这样的函数,于是我们就在父类中写一个虚函数。这个虚函数也可以有一个默认实现,比如说

此时如果说我们在实例化一个dog子类和cat子类,我们去调用它的work方法的时候,它调用的都是这个animal的work方法。
如果说我们要在子类当中重写父类的某一个方法,我们就需要在类的声明当中写出和父类一样的方法签名,然后在后面写上override关键词
之后呢,我们再去完成这个函数的实现,由此就可以完成这个方法的重写,如图所示
这个时候如果说我们实例化一个dog子类,然后去调用它的work函数,那么它就会输出这个dog。在更复杂的例子当中,比如说这个let it work函数,按理来说,这个函数只知道传进去的是一个animal类型,它应当去调用这个基类的一个work函数,但是我们看到它可以根据传进去的这个类型来灵活的调用当前类型的函数,可见完成了多态

去掉override试试

此时我们去掉了这个虚函数的声明和所有的这个override重写,此时我们会发现它已经没有刚才的多态的效果,这是最终返回的结果来看,均是调用了animal的函数
什么原理?

编译器在实现的时候,类似于在实例化的对象的结构体内放置了一个针对于虚函数的指针也就是虚函数表vfptr


我们可以实验一下,这时候我们把所有虚函数的这个关键字全都给取掉,然后我们给定义一个这个成员变量a之后,我们用size of操作符来看一下大小
果然,正如我们所料程序返回了四,也就是这个成员变量占据的空间大小
此时我们把这个virtual函数给它加上去,这个时候继续运行相同的程序,我们发现它返回了16,也就是说它为这个函数指针给增加了一个内存空间
构造函数和析构函数


如图所示,我们在此搭建了两个类,分别为其添加了构造函数和析构函数,在子类的参数初始化列表当中,我们调用父类的构造函数,以正确的初始化父类的缓冲区。在析构函数当中,我们去释放变量。
此时,为了检验析构函数是如何调用的,我们在析构函数当中可以增加一些这个print,之后呢,我们创建一个类型为child,的一个变量,然后我们试试再去使用delete操作符释放它分配的空间,看到操作台的打印,结果我们发现在析构的过程当中C加加优先调用了子类的析构函数,之后调用父类的析构函数



此时,我们在创建一个子类二,然后使用工厂函数来去创建不同类型的子类,并且去销毁它
此时,我们使用工厂函数来创建一个类型为child one,的一个子类,再用销毁函数来去析构它的内存,此时我们发现了问题,最终只调用了父类的这个析构函数。
我们给这个父类的析构函数,加上virtual虚函数标识,再做一次实验,此时我们发现依次调用了子类和父类的析构函数,综上可知,在做类的继承的时候,父类的析构函数需要标记为虚函数
实际上来说,非final类的析构函数需要标记为这个虚函数
如果说你的这一个类,他没有任何的这个子类,并且你懒得再去加virtual来标记,那么你可以将这个类标记为final类来确保它的析构函数,不会被任何继承它的子类进行一个覆盖
343

被折叠的 条评论
为什么被折叠?



