Java多态(动态绑定)的底层原理:虚函数表

部署运行你感兴趣的模型镜像


为了实现Java方法调用的动态绑定,HotSpot使用了与C++虚函数类似的机制,同时为了避免每个对象都维护一个虚函数表,就是设计了Oop-Klass模型,用Klass类保存类的元数据和虚函数表。

多态的理解

从java语言层面看,多态是指在编译期间不确定实际类型,在运行期间才根据实际类型调用具体的方法,一般在接口的多实现和类的继承有具体体现。
从JVM内部角度看,java多态的实现是通过itable(interface method table:接口方法表), vtable(virtual method table:虚函数表)来实现方法的准确跳转。
Java中的普通方法(没有static和final修饰)是动态绑定的,在C++中动态绑定通过虚函数来实现,代价是每个C++对象都必须维护一张虚函数表。Java的特点就是一切皆是对象,如果每个对象都维护一张虚函数表,内存开销将会非常大。JVM对此做了优化,虚函数表不再由每个对象维护,改成由oop-klass模型的Klass类型维护,所有属于同一类型的所有对象共用一张虚函数表。
注意: C++是每个对象持有虚函数表,java是通过OOP对象指向Klass对象,Klass对象持有该类的虚函数表,所有该类的对象共用一张虚函数表。java的普通方法都会在JVM都会在内部表示为类似于C++的虚函数。

C++的虚函数和纯函数的区别

纯函数: 在基类中只进行声明,不进行具体实现,而在子类进行具体实现,类似于java接口中的方法。
注意: C++允许多重继承,是通过抽象类来实现java中接口作用的,抽象类中都是纯函数
虚函数: 在基类中,使用virtual关键字修饰的函数,且有具体的实现,其子类可以覆写该虚函数,也可以不覆写该函数。虚函数在C++中的主要作用:实现多态和多重继承。

虚函数表

每一个含有虚函数(无论虚函数是其本身的,还是继承而来的)的类都至少有一个与之对应的虚函数表,其存放着该类所有虚函数对应的函数指针。
在这里插入图片描述

虚函数表的构造过程

子类重基类中拷贝一份虚函数表,使子类的虚函数表指针指向新的虚函数表,如果子类中覆写了基类的虚函数,则将函数表中覆写函数的函数指针替换为子类覆写的函数指针,如果子类中有新增的虚函数,则在该子类的虚函数表中追加新增的虚函数指针。
在这里插入图片描述

虚函数的调用过程

在这里插入图片描述
C++编译时,只知道pb是B类型的指针,并不知道该指针具体指向哪个对象,但无论pb指向哪个对象,被调用函数在虚函数表中偏移量是固定的,运行时根据传入对象的具体类型,找到对应的虚函数表,再根据相同虚函数在基类和不同子类中的偏移量相同,找到对应的虚函数执行。
多重继承: C++允许多重继承,当一个类继承多个类,且多个基类都有虚函数时,子类对象中将包含多个虚函数表的指针。
在这里插入图片描述

您可能感兴趣的与本文相关的镜像

ACE-Step

ACE-Step

音乐合成
ACE-Step

ACE-Step是由中国团队阶跃星辰(StepFun)与ACE Studio联手打造的开源音乐生成模型。 它拥有3.5B参数量,支持快速高质量生成、强可控性和易于拓展的特点。 最厉害的是,它可以生成多种语言的歌曲,包括但不限于中文、英文、日文等19种语言

评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值