C++与Java中多态实现机制的区别

一种错误的观点是:c++与java多态性的实现机制不同,但它们的表现形式应该相同。以下我将举出两个例子(请耐心看)。

class Super { 
    public Super() { 
        init(); 
    }
    protected void init() {
        System.out.print("1:Super"); 
    } 
}
public class Sub extends Super{ 
    public Sub(){
        init();
    } 
    public void init() { 
        System.out.print("2:Sub"); 
    }
    public static void main(String[] args) 
    {  
        Super test=new Sub(); 
        // 输出
        // 2:Sub 2:Sub
    } 
}

如果换成C++相信大家都知道会输出 1:Super 2:Sub

1. C++中的函数调用方式
  • 普通函数调用:具体调用哪个方法在编译时间就可以决定(通过查找编译器的符号表),同时在使用标准过程调用机制基础上增加一个表示对象身份的指针(this指针)。
  • 虚函数调用:函数调用依赖于对象的实际类型,一般地说,对象的实际类型只能在运行时间才能确定。虚函数一般要有两个步骤来支持,首先每一个类产生出一堆指向虚函数的指针,放在表格中,这个表格就叫虚函数表(virtual table);然后每一个类对象(class object)会添加一个指向相关虚函数表(virtual table)的指针,通常这个指针叫做vptr(自己动手写几个虚函数试试,检查class的size ,会发现明显变大。C++中Vptr放在每个对象实例内存最开始的位置)。
2. Java中的函数调用方式
  • 在java虚拟机中,类实例的引用(实例对象名)就是指向一个句柄(handle)的指针,而该句柄其实是一对指针:其中一个指针指向一张表,该表格包含了对象的方法列表以及一个指向类对象(表示对象类型)的指针;另一个指针指向一块内存地址,该内存是从java堆中为对象的数据而分配出来的。



现在回到我们刚才的例子,java中的类对象在构造前(调用构造函数之前)就已经存在了,其函数表和对象类型也已经确定了,就是说还没有出生就已经存在了。

而C++中只有在构造完毕后(所有的构造函数都被成功调用)才存在,其函数表和对象的实际类型才会确定。所以这两个例子的执行结果会不一样。(个人的猜测是先构建父类对象,所以此时虚函数指针指向的是父类的虚函数,当构建子类时,虚函数指针被覆盖为子类虚函数,每一层构造都完成后,虚函数指针才被确定)

从这个例子,我们可以看出这样一个陷阱——java例子中按照逻辑应该执行的初始化函数,没有执行,即父类的初始化函数没有得到执行,这点在写代码是要注意规避。

最后讲讲java中,属性与方法的隐藏与覆盖的例子。

package Temp;

class Parent{

          int x=10; 
          public Parent(){ 
              System.out.println("1:" + x);
               add(2); 
               System.out.println("2:" + x);
          } 
          void add(int y){ 
               System.out.println("3:" + x);
               x+=y; 
               System.out.println("4:" + x);
          } 
     }

class Child extends Parent{ 
     int x=9; 
     void add(int y){ 
          System.out.println("5:" + x);
          x+=y; 
          System.out.println("6:" + x);
     } 
     public static void main(String[] args){ 
          Parent p=new Child(); 
          System.out.println(p.x); 
     }   
}

输出为:
1:10
5:0
6:2
2:10
10

有兴趣可以研究为什么这样。

本文是我在看了这篇文章后的总结。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值