首页 技术 正文
技术 2022年11月15日
0 收藏 962 点赞 3,345 浏览 1530 个字

多态是指用父指针指向不同子类对象时,调用其共有的函数,不同的子类会有不同的行为。虽然C++和Java都具有多态机制,但是他们的实现不同,使用时的效果也会略有不同。

在C++中

  • 普通函数调用:具体调用哪个方法在编译时就可以决定(通过查找编译器的符号表),同时在使用标准过程调用机制基础上增加一个表示对象身份的指针(this指针)。
  • 虚函数调用:函数调用依赖于对象的实际类型,一般地说,对象的实际类型只能在运行时间才能确定。实现机制是使用virtual table(vtbls)和virtual table pointers(vptrs)。
    1. vtbl 是由函数指针构成的数组或链表,程序中每一个class凡声明(或继承)虚函数者,都有一个自己的vtbl,其中的条目就是该class的各个虚函数实现的指针。因此必须为每一个class消耗一个vtbl空间,其大小视虚函数的个数确定。
    2. 凡声明有虚函数的class,其对象都有一个隐藏的data member,用来指向class的vtbl。
    3. 当多态发生时,编译器首先根据对象vptr找出其vtbl,然后找出vtbl内对应的函数指针,最后调用函数指针指向的函数。从而实现多态。

在Java中

1.C++中VTable和vptr是在编译阶段由编译器自动生成的,也就是说,在C++程序载入内存以前,在.obj(.o)文件中已经有这些结构的信 息;Java中的方法表是由JVM生成的,因此,使用javac命令编译后生成的.class文件中并没有方法表的信息。只有等JVM把.class文件 载入到内存中时,才会为该.class文件动态生成一个与之关联的方法表,放置在JVM的方法区中。

2. C++中某个方法在VTable的索引号是在编译阶段已经明确知道的,并不需要在运行过程中动态获知;Java中的方法初始时都只是一个符号,并不是 一个明确的地址,只有等到该方法被第一次调用时,才会被解析成一个方法表中的偏移量,也就是说,只有在这个时候,实例方法才明确知道自己在方发表中的偏移 量了,在这之前必须经历一个解析的过程。

因此在构造函数是Java会发生多态,即使子类此时还没有构造完全(一个极难发现的bug)。而C++则不会发生多态,待父类构造完全,在构造子类。

Java代码如下:

public class A {
public void fun()
{
System.out.println("A");
}
public A()
{
this.fun();
}
}
public class B extends A{
public void fun()
{
System.out.println("B");
} public B()
{
fun();
}
public static void main(String [] argv)
{
B b = new B();
}
}
//B
//B

C++代码如下:

#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
using namespace std;
class A
{
public:
virtual void fun()
{
cout<<"A"<<endl;
}
A()
{
fun();
}
};
class B : A
{
public:
virtual void fun()
{
cout<<"B"<<endl;
}
B()
{
fun();
}};
int main(int argc, char *argv[])
{
B b;
}
//A
//B

可以发现,C++构造子类时,先构造父类,输出A,然后在构造自身,输出B。而Java在构造子类时,父类并未构造完成,但已经可以发生多态输出B,然后再构造自身,输出B。Java一般为了避免这种情况,会把fun等init()函数声明为private或者finial。

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,489
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,904
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,737
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,490
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:8,128
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:5,291