C++面向对象-23-多态原理剖析

前面一篇学习了多态,有静态多态和动态多态之分。动态绑定是第一需要继承关系,第二是子类需要重写父类的函数。什么是重写,从函数返回值,函数名称和参数列表一模一样才叫函数重写。本篇就借助vs 开发工具来捋一捋多态的底层原理。

 

1.两个单词概念

在前面多继承的时候,我们也介绍了虚继承,其中使用了virtual,当时有vbptr虚基类指针和vbtable虚基类表,其中作用是vbptr指向了vbtable。这次多态底层原理学习也需要理解类似的两个概念。

虚函数指针 vfptr,vritual function pointer

虚函数表 vftable, virtual function table

虚函数指针的作用是指向虚函数表。

 

2.不带virtual的Animal类占内存大小

代码和前面一篇一样,当前这里操作需要删除代码中Animal基类虚函数前面vritual,先看看这个父类不带virtual所占内存大小

不带virtual,而且当前Anima类没有什么成员变量,所以所占内存就1个字节。

 

2.带virtual的Animal类占内存大小

在Animal基类中加上virtual,运行上面命令,看看占内存是多少

加上virtual关键字之后,所占内存为4字节,不用怀疑和乱猜测,这里四个字节就是一个指针大小,前面学习过,任何类型的指针所占内存大小都是4字节,这里这个指针就是vfptr,也就是文章开头的虚函数指针。注意上面,这个vfptr指向vftable,在虚函数表中,当前存储的是 &Animal::speak,Animal::这个是作用域,表示存储的是Animal类的speak函数,前面加上&符号,就表示Animal类中speak函数的地址。

 

3.静态绑定的时候子类Cat中存储内容

现在我们又来去除基类Animal中虚函数前面的关键字virtual,把上面命令变成查询子类Cat的继承关系情况。

这个时候,子类中可以看到父类是Animal, 而且子类所占内存大小1字节,这里没有vfptr,也就是虚函数指针,子类继承父类的全部,所以调用speak函数,输出的内容是父类中speak函数的结果。

 

4.动态绑定子类Cat中存储的内容

把前面删除关键字virtual添加回来,再次查询子类Cat的继承关系

这个时候动态绑定,子类Cat中显示父类是Animal, 还有一个虚函数指针,这个是父类继承过来的,所以字节大小是4。这个时候虚函数指针指向虚函数表,此时虚函数表中存储的是&Cat::speak 这个很清楚写明白了,存储的是子类Cat作用域下speak函数的内存地址。所以,动态绑定下,doSpeak函数传入参数是什么子类对象,就调用该子类对象中的speak方法。因为虚函数表中用子类中的同名函数覆盖了原来父类的虚函数。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值