4月14日多态的笔迹总结,

发布时间 2023-04-15 23:42:52作者: 玄灵镜

1.声明的虚函数若等于零则叫纯虚函数。他不能被不重写继承,且可以代表一些实例化对象抽象的概念。

2.对于虚函数接口继承的理解:普通函数是继承函数所有的东西,派生类就是为了调用这个函数而继承,而虚继承则是继承了这个函数的接口,函数的实现部分需要派生类去重写,从而达成多态。

3.虚函数在类里面以一个虚表里面的指针形式存在着,当派生类继承虚函数时,派生类里面就会新生成一个虚表,若是派生类重写了基类的虚函数,那么派生类实例化对象虚表下的虚函数指针就会与基类不一样,从而调用派生类重写过的函数指针。

4,多态是一个动态重载,他是在运行时来确定需要调用的函数指针来调用函数。而静态重载是在编译时就确定了要调用的函数指针从而直接调用函数,不需要查找,

5.一个函数有多个指令,而函数指针则是函数的第一条指令的指针,

普通函数与虚函数多态时调用的区别,普通函数是直接找到这个函数的指针去使用,什么类型就调用那个类型下的函数,而多态则是,当指针或引用去调用,且函数为虚函数时,这个引用或指针就会在他们所指向的实例化对象下的虚表中去找对应的重写函数的指针,从而使用函数,函数的地址基本存在于常量区代码段,

静态绑定:相当于重载函数,他在编译时就确定了要调用函数的地址,而动态绑定:相当于多态,他是在程序运行时才不断确定函数的地址,

复习c语言中的指针表示:指针数组的表示:int* (*P) [9]表示数组的指针,void(*P)(int,int)表示函数的指针,要注意的是他们在声明时将指针的变量名写在前面,

打印虚函数表的原理:因为虚表在类中存在最前面且是一个指针数组指针的形式存在,因为指针与整形所占的字节是一样的,所以可以先将对象强转为整形指针类型使其在32位系统下只访问四个字节,再将这个指针解引用得到数组的首元素也就是虚表下第一个虚函数的指针,再次将这个指针强转为定义好的指针类型就可以循环打印虚函数的指针了。

若派生类多继承了好几个基类的虚函数,那么这个派生类就有多个虚表,每个虚表与其基类一一对应,

上图可以看到,b和c同时时d的派生类,且没有发生函数重写,但是他们的虚表指针不一样所以基类与派生类不是共用一张虚表不管有没有发生重写,但是b和c却用的是同一张虚表,所以同一类型共用一张虚表。之前有说到析构函数需要写成虚函数来一起析构派生类和基类,当this指针指向派生类时调用派生类的虚析构函数,当指向基类时调用基类的虚析构函数。那么构造函数可否写成虚函数呢

因为虚表是在构造函数初始化列表时才初始化的,所以构造函数不可以写成虚函数,

虚基表和虚表虽然只差了一个字但是他们之间没有关联,虚基表是为了解决类菱形继承导致数据冗余和变量二义性副作用而存在的,他的实现原理是将虚基类的变量放在一个公共位置,原本存放冗余变量的地方变为一个指针,指向一个偏移量,这个指针可以根据这个偏移量来找到冗余的变量,从而解决菱形继承的缺点。当一个派生类虚继承多次基类时,当这个派生类初始化时虚基表下的变量构造只会初始化一次。