Java和C++中多态的实现方式
多态是面向对象的最主要的特性之一,是一种方法的动态绑定,实现运行时的类型决定对象的行为。多态的表现形式是父类指针或引用指向子类对象,在这个指针上调用的方法使用子类的实现版本。多态是IOC、模板模式实现的关键。
在C++中通过虚函数表的方式实现多态,每个包含虚函数的类都具有一个虚函数表(virtual table),在这个类对象的地址空间的最靠前的位置存有指向虚函数表的指针。在虚函数表中,按照声明顺序依次排列所有的虚函数。比如:
class Base {
public:
virtual void f() {
printf("Base::f()");
}
virtual void g() {
printf("Base::g()");
}
};
class Derived: public Base {
public:
virtual void f() {
printf("Derived::f()");
}
};
上面代码对应的类布局:
由于C++在运行时并不维护类型信息,所以在编译时直接在子类的虚函数表中将被子类重写的方法替换掉,如上图的Derived::f(),这个方法会被放到虚函数表中原来父函数在的位置。由于在编译时就确定了虚函数在虚表中的下标,所以在进行虚函数调用时,直接根据下标进行访问。比如,调用Derived对象上的f():
Base *b = new Derived;
b->f();
在调用b->f()时,内部会转化成(*b->vptr[1])(),由于虚函数表需要完成RTII,所以虚函数表的第一个slot存放的是type info,虚函数下标从1开始。实际上,虚函数表记录了这个类的所有虚函数的具体实现(就是在运行时确切要调用的),编译时就可以确定,不需要动态查找,效率较高。
而Java中,在运行时会维持类型信息以及类的继承体系。每一个类会在方法区中对应一个数据结构用于存放类的信息,可以通过Class对象访问这个数据结构。其中,类型信息具有superclass属性指示了其超类,以及这个类对应的方法表(其中只包含这个类定义的方法,不包括从超类继承来的)。而每一个在堆上创建的对象,都具有一个指向方法区类型信息数据结构的指针,通过这个指针可以确定对象的类型。
JVM中用于方法调用的指令包括:
invokevirtual:用于调用实例方法,会根据对象的实际类型进行调用。
invokespecial:需要特殊处理的实例方法,比如:public final方法、私有方法和父类方法等。调用的方法取决于引用的类型。
invokeinterface:调用接口的方法。
invokestatic:调用类方法。
按照上面描述,对于子类覆盖父类的方法,编译后,调用指令应该是invokevirtual,调用的方法取决于对象的类型。invokevirtual方法查找的实现方式是:
1. 通过对象中类指针找到其类信息,然后在方法表中根据方法签名找到该方法。
2. 如果不在当前类,则递归查找其父类的方法表直到Object类。
3. 如果找到Object类,也没有该方法,会抛出NoSuchMethodException异常。
与js、lua等动态语言类似,Java的实现方式依赖于内存中的类型体系信息,存在一个“原型链”,是一个完全动态的查找过程,相对于C++而言,效率会低一些,因为存在一个链表遍历查找的过程。之所以,Java中可以这样实现,本质上是因为它是一门虚拟机语言,虚拟机会维持所有的这些类型信息。
Java和C++中多态的实现方式的更多相关文章
- 关于java中多态的理解
java三大特性:封装,继承,多态. 多态是java的非常重要的一个特性: 那么问题来了:什么是多态呢? 定义:指允许不同类的对象对同一消息做出响应.即同一消息可以根据发送对象的不同而采用多种不同的行 ...
- 个人对Java中多态的一些简单理解
什么是多态 面向对象的三大特性:封装.继承.多态.从一定角度来看,封装和继承几乎都是为多态而准备的.这是我们最后一个概念,也是最重要的知识点. 多态的定义:指允许不同类的对象对同一消息做出响应.即同一 ...
- Java中多态的一些简单理解
什么是多态 .面向对象的三大特性:封装.继承.多态.从一定角度来看,封装和继承几乎都是为多态而准备的.这是我们最后一个概念,也是最重要的知识点. .多态的定义:指允许不同类的对象对同一消息做出响应.即 ...
- Java 第18章 多态
18 章 --> 多态 继承: extends 抽象类 abstract (限制类的实例化) 抽象方法 public abstract void show(); //抽象方法只有方法的声明,没 ...
- 深入Java核心 Java中多态的实现机制(1)
在疯狂java中,多态是这样解释的: 多态:相同类型的变量,调用同一个方法时,呈现出多中不同的行为特征, 这就是多态. 加上下面的解释:(多态四小类:强制的,重载的,参数的和包含的) 同时, 还用人这 ...
- Java多态与C++中多态的实现
大牛的文章,值得拜读http://www.ibm.com/developerworks/cn/java/j-lo-polymorph/ 粘贴过来好多图片丢失了 /(ㄒoㄒ)/~~ 众所周知,多态是面向 ...
- 从虚拟机指令执行的角度分析JAVA中多态的实现原理
从虚拟机指令执行的角度分析JAVA中多态的实现原理 前几天突然被一个"家伙"问了几个问题,其中一个是:JAVA中的多态的实现原理是什么? 我一想,这肯定不是从语法的角度来阐释多态吧 ...
- JS 和 Java 中URL特殊字符编码方式
前几天遇到url特殊字符编码的问题,在这里整理一下: JavaScript 1. 编码 escape(String) 其中某些字符被替换成了十六进制的转义序列. 解码 unescape(String ...
- Java中数组的初始化方式
Java中数组的初始化方式 初始化方式有两种: 1.静态初始化:初始化时由程序猿显式指定每一个数组元素的初始值,由系统指定数组长度 2.动态初始化:初始化时由程序猿仅仅指定数组长度,由系统为数组 ...
随机推荐
- ISO-8859-1
ISO-8859-1编码是单字节编码,向下兼容ASCII,其编码范围是0x00-0xFF,0x00-0x7F之间完全和ASCII一致,0x80-0x9F之间是控制字符,0xA0-0xFF之间是文字符号 ...
- 数往知来 AJAX Ajax增删改查<十九>
=================================================客户端================================================ ...
- scala 连接 mysql
code: import java.sql.{ResultSet, DriverManager} import com.mysql.jdbc.Connection object hoursAvg { ...
- kerboros安装
尽管前面尝试了hadoop的simple认证方式,这种方法不是特别安全,在介绍一下hadoop的kerberos方式之前,下面我们尝试一下kerberos. 首先介绍一下Kerboros安装 OS 版 ...
- Python线程
原文出处: AstralWind 1. 线程基础 1.1. 线程状态 线程有5种状态,状态转换的过程如下图所示: 1.2. 线程同步(锁) 多线程的优势在于可以同时运行多个任务(至少感觉起来是这样). ...
- WebService调用一对多关联关系时出现 死循环:A cycle is detected in...
通过WebService调用一对多关联关系时引起的问题:A cycle is detected in the object graph 具体异常信息: org.apache.cxf.intercept ...
- navigationController 之间的切换
项目要实现从一个Navigation 下push出的第N层controller后 立即切换到另一个 Navigation下 例如:在微信的通讯录Nav中选择一个好友,进入好友的详细资料,点击发消息按钮 ...
- nodejs 基本操作
查看nodejs版本 nodejs -v 升级nodejs node有一个模块叫n(这名字可够短的...),是专门用来管理node.js的版本的.首先安装n模块:npm install -g n 第二 ...
- hdu 4738 Caocao's Bridges(桥的最小权值+去重)
http://acm.hdu.edu.cn/showproblem.php?pid=4738 题目大意:曹操有一些岛屿被桥连接,每座都有士兵把守,周瑜想把这些岛屿分成两部分,但他只能炸毁一条桥,问最少 ...
- win7 文件共享 xp
前几天因为需要将win7内一文件夹共享给XP使用,因为NT5跟NT6安全机制的问题,共享的实现没有XP共享的方便,很多人是牺牲(关闭)了win7的系统防火墙才达到共享给XP的目的,但是关闭防火墙势必会 ...