多态是面向对象的最主要的特性之一,是一种方法的动态绑定,实现运行时的类型决定对象的行为。多态的表现形式是父类指针或引用指向子类对象,在这个指针上调用的方法使用子类的实现版本。多态是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++中多态的实现方式的更多相关文章

  1. 关于java中多态的理解

    java三大特性:封装,继承,多态. 多态是java的非常重要的一个特性: 那么问题来了:什么是多态呢? 定义:指允许不同类的对象对同一消息做出响应.即同一消息可以根据发送对象的不同而采用多种不同的行 ...

  2. 个人对Java中多态的一些简单理解

    什么是多态 面向对象的三大特性:封装.继承.多态.从一定角度来看,封装和继承几乎都是为多态而准备的.这是我们最后一个概念,也是最重要的知识点. 多态的定义:指允许不同类的对象对同一消息做出响应.即同一 ...

  3. Java中多态的一些简单理解

    什么是多态 .面向对象的三大特性:封装.继承.多态.从一定角度来看,封装和继承几乎都是为多态而准备的.这是我们最后一个概念,也是最重要的知识点. .多态的定义:指允许不同类的对象对同一消息做出响应.即 ...

  4. Java 第18章 多态

    18 章  --> 多态 继承: extends 抽象类 abstract (限制类的实例化) 抽象方法 public abstract void show(); //抽象方法只有方法的声明,没 ...

  5. 深入Java核心 Java中多态的实现机制(1)

    在疯狂java中,多态是这样解释的: 多态:相同类型的变量,调用同一个方法时,呈现出多中不同的行为特征, 这就是多态. 加上下面的解释:(多态四小类:强制的,重载的,参数的和包含的) 同时, 还用人这 ...

  6. Java多态与C++中多态的实现

    大牛的文章,值得拜读http://www.ibm.com/developerworks/cn/java/j-lo-polymorph/ 粘贴过来好多图片丢失了 /(ㄒoㄒ)/~~ 众所周知,多态是面向 ...

  7. 从虚拟机指令执行的角度分析JAVA中多态的实现原理

    从虚拟机指令执行的角度分析JAVA中多态的实现原理 前几天突然被一个"家伙"问了几个问题,其中一个是:JAVA中的多态的实现原理是什么? 我一想,这肯定不是从语法的角度来阐释多态吧 ...

  8. JS 和 Java 中URL特殊字符编码方式

    前几天遇到url特殊字符编码的问题,在这里整理一下: JavaScript 1.  编码 escape(String) 其中某些字符被替换成了十六进制的转义序列. 解码 unescape(String ...

  9. Java中数组的初始化方式

    Java中数组的初始化方式    初始化方式有两种: 1.静态初始化:初始化时由程序猿显式指定每一个数组元素的初始值,由系统指定数组长度 2.动态初始化:初始化时由程序猿仅仅指定数组长度,由系统为数组 ...

随机推荐

  1. 镜头覆盖范围FOV 的规划与FOV去四角

    本文纲要: 规划FOV的原因 FOV去四角 简单的声明 FOV查找思路 查找FOV的代码 TNoFourCornersRect结构及Contains函数 判断两个矩形是否相交 延伸与拓展 本文内容: ...

  2. 初学JavaScript(入门一)

    javaScript是世界上最流行的脚本语言   在我们的手机.电脑设备上所浏览的所有网页,以及基于HTML5手机App的交互都是通过javaScript驱动的,所以javascript是前端工作的一 ...

  3. 【转】asp.net发布到IIS中出现错误:处理程序“PageHandlerFactory-Integrated”在其模块列表中有一个错误模块“ManagedPipelineHandler”

    原文:http://blog.csdn.net/mazhaojuan/article/details/7660657 开发web项目时需要安装IIS,在安装好IIS的Windows7本上发布asp.n ...

  4. 使用源码编译wxpython-基于python2.7

    1.前言 本文主要讲述在linux环境下进行编译wxpython,在windows下面安装wxpython很简单,只要下载,然后直接执行exe文件,下一步下一步即可安装,在linux下面,则具有很多步 ...

  5. Maven 包命令

    1.必须选中项目,然后单击Run As,选择Maven build. 2.在配置窗体中的Goals栏填写clean package. 注意:Installed JREs中配置的JREs的位置必须是JD ...

  6. 20150926kaggle Titanic入门篇excel&python

    1 excel数据透视表 这里主要是讲述了一下插入里面的数据透视表常用功能,数据透视表十分方便,比直接筛选还要简单,看数据很直观,这里大力推荐. 2 python&pandas 这里主要是讲述 ...

  7. c++声明与定义

    c++声明与定义 声明是将一个名称引入程序.定义提供了一个实体在程序中的唯一描述.声明和定义有时是同时存在的. 如 int  a; extern int b=1; 只有当extern中不存在初始化才是 ...

  8. 解决SQL Server Always 日志增大的问题-摘自网络

    配置了Alwayson之后,因为没有只能使用完全恢复模式,不能使用简单或大容量日志模式,所以日志不断增长,不能使用改变恢复模式的方式清空日志 手动操作收缩或截断日志也无效 读了一些文章后发现,有人使用 ...

  9. 如何开启多用户同时远程连接(Windows2008 Windows2012)

  10. 借助LVS+Keepalived实现负载均衡(转)

    原文:http://www.cnblogs.com/edisonchou/p/4281978.html 一.负载均衡:必不可少的基础手段 1.1 找更多的牛来拉车吧 当前大多数的互联网系统都使用了服务 ...