C++与Java中多态实现机制的区别
2017-12-03 18:33
387 查看
一种错误的观点是:c++与java多态性的实现机制不同,但它们的表现形式应该相同。以下我将举出两个例子(请耐心看)。
如果换成C++相信大家都知道会输出 1:Super 2:Sub
虚函数调用:函数调用依赖于对象的实际类型,一般地说,对象的实际类型只能在运行时间才能确定。虚函数一般要有两个步骤来支持,首先每一个类产生出一堆指向虚函数的指针,放在表格中,这个表格就叫虚函数表(virtual table);然后每一个类对象(class object)会添加一个指向相关虚函数表(virtual table)的指针,通常这个指针叫做vptr(自己动手写几个虚函数试试,检查class的size ,会发现明显变大。C++中Vptr放在每个对象实例内存最开始的位置)。
现在回到我们刚才的例子,java中的类对象在构造前(调用构造函数之前)就已经存在了,其函数表和对象类型也已经确定了,就是说还没有出生就已经存在了。
而C++中只有在构造完毕后(所有的构造函数都被成功调用)才存在,其函数表和对象的实际类型才会确定。所以这两个例子的执行结果会不一样。(个人的猜测是先构建父类对象,所以此时虚函数指针指向的是父类的虚函数,当构建子类时,虚函数指针被覆盖为子类虚函数,每一层构造都完成后,虚函数指针才被确定)
从这个例子,我们可以看出这样一个陷阱——java例子中按照逻辑应该执行的初始化函数,没有执行,即父类的初始化函数没有得到执行,这点在写代码是要注意规避。
最后讲讲java中,属性与方法的隐藏与覆盖的例子。
输出为:
1:10
5:0
6:2
2:10
10
有兴趣可以研究为什么这样。
本文是我在看了这篇文章后的总结。
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
有兴趣可以研究为什么这样。
本文是我在看了这篇文章后的总结。
相关文章推荐
- java 和C++ 多态机制区别
- Java和C++访问权限以及多态机制的一些区别
- java c++ 实现多态(polymorphism)的机制
- Java和C++的区别以及Java的垃圾回收机制
- c++实现多态的原理和机制
- C++和java中多态机制的异同
- Java与C++的区别之构造函数中的多态
- C++和java中多态机制的异同
- C++内联函数跟普通函数的区别以及实现机制
- C++和java中多态机制的异同
- JAVA中实现多态的机制是什么?
- 深入总结Java中多态实现机制
- 【转】C语言实现C++面向对象的封装、继承、多态机制
- 多态在 Java 和 C++ 编程语言中的实现比较
- java中实现多态的机制
- java多态的实现机制
- Java中多态的实现机制
- 独家披露C++和java多态的区别
- Java中多态的实现机制
- 一个新的对象创建机制的思考--C++下实现类似于Java的对象管理机制及反射