C++多态----虚函数初级剖析

多态说白了就是多种形态,在C++中不少的函数都可以实现多种形态,例如函数重载,运算符重载等等,这种重载一般都是在编译阶段时就已经确定了形态,这种多态,我们一般称之为静态多态,那么既然静态多态是在编译阶段就已经确定好了形态,那么动态多态,自然也就是在运行时才确定形态

请看如下代码:

现在调用Speak全局函数所得到的结果只会是动物在说话,为什么呢,因为这个全局函数在编译阶段时就已经通过函数参数确定了这是一个Animal类的Speak成员函数,那么我们想让猫传过去就调用猫的Speak,狗传入就调用狗的Speak,就需要用到关键字virtual,在Animal下的Speak函数前加上 此关键字,即可让此成员函数变为虚函数,我们也可以让Speak全局函数实现谁传入就调用谁的Speak,那么这一原理究竟是什么呢,下面我们来进行简单的剖析

首先我们借助visual studio的开发人员工具来帮助我们剖析,在vs的PowerShell下进入到源文件所属文件夹路径下,再输入 cl /d1 reportSingleClassLayout类名 + 源文件名后可以看到此类的所有属性

这是没有加virtual关键字的Animal:

仅显示了大小为1,因为这是个空类,空类的大小都为1,这是加了virtual关键字的Animal

 可以发现多了一个vfptr和vftable,vfptr:v指virtual,可以理解为虚的意思,f指functino,ptr自然就是pointer,意为虚函数指针,所指向的就是vftable,vftable意为虚函数表,里面存放着:&Adnimal::speak ,也就是虚函数的地址,我们再来看猫类不重写Speak函数的属性

 可以发现Cat类没有重写函数时的虚函数表中是通过Animal继承过来的Animal下的Speak函数地址,那重写后的为:

 可以发现,Cat重写Speak函数后,虚函数表内的函数地址由Animal的函数地址替换为了Cat的函数地址,所以我们在调用Speak全局函数时,只要Speak的函数参数通过& 来接收,甭管你什么类名,都是我Cat的别名,那我们现在Cat所指向的虚函数表中所记录的是我Cat的虚函数地址,跟你Animal就没有任何关系,所以就回调用Cat的Speak函数

简单总结一下,实现动态多态就是依靠虚函数,而虚函数内部又有虚函数指针和虚函数表,当继承者继承过去但没有发生重写虚函数时,内部所记录的就是父类的虚函数地址,一旦重写,就会将虚函数表中的父类地址给替换为自己的地址,使用时只要是使用子类对象时,不管如何将父类强加于身,我们所调用重写过的虚函数地址时都会是调用自己的函数地址,主要原因就是函数列表中的替换

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值