美文网首页
Java和C++中多态的实现方式

Java和C++中多态的实现方式

作者: 海纳百川_spark | 来源:发表于2016-06-02 09:54 被阅读237次

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

    多态是面向对象的最主要的特性之一,是一种方法的动态绑定,实现运行时的类型决定对象的行为。多态的表现形式是父类指针或...

  • php面向对象的多态性

    多态是除封装和继承之外的另一个面象对象的三大特性之一,我个人看来PHP中虽然可以实现多态,但和c++还有Java这...

  • C++编译期多态和运行期多态

    C++多态有多种实现方式,在面对对象编程时,采用的是运行期多态,也称动态多态。在泛型编程中,多态基于模板的具现化与...

  • 聊聊Java的泛型及实现

    摘要: 和C++以模板来实现静多态不同,Java基于运行时支持选择了泛型,两者的实现原理大相庭径。C++可以支持基...

  • Java编程思想重点笔记

    1. Java中的多态性理解(注意与C++区分) Java中除了static方法和final方法(private方...

  • Swift 多态实现探究

    多态 父类指针指向子类对象 Swift 中多态的实现类似于 c++ 中的虚表 OC 多态实现利用的是 Runtim...

  • 深刻剖析之c++博客文章

    三大特性 封装、继承、多态 多态 C++ 虚函数表解析C++多态的实现原理 介绍了类的多态(虚函数和动态/迟绑定)...

  • C++ 虚函数 总结

    虚函数是 C++ 实现多态的方式。 什么是多态?多态性常被视为自封装和继承之后,面向对象的编程的第三个支柱。如果举...

  • 多态在内存中的实现--虚函数表

    引入 虚函数本是c++中的概念,但在java中应用非常广泛,因为虚函数是为了实现多态而生,需要为函数添加vritu...

  • java抽象类和接口小记

    Java抽象类和接口小记 Java抽象类和接口实现了java的多态.多态是面向对象程序语言的核心,在项目开发过程中...

网友评论

      本文标题:Java和C++中多态的实现方式

      本文链接:https://www.haomeiwen.com/subject/utfkdttx.html