当前位置: 技术问答>java相关
java菜鸟问一个类似c++中vtable的问题
来源: 互联网 发布时间:2015-07-28
本文导语: java要支持虚函数,所以会用到类似c++中的vtable, 在c++中,如果类C多重继承自两个不同的抽象类(类A和类B),那么类C中就会有 两个vtable,一个存放类A的虚函数指针,另一个存放类B的虚函数指针, 那么请问: 如果我的一...
java要支持虚函数,所以会用到类似c++中的vtable,
在c++中,如果类C多重继承自两个不同的抽象类(类A和类B),那么类C中就会有
两个vtable,一个存放类A的虚函数指针,另一个存放类B的虚函数指针,
那么请问:
如果我的一个java类继承了两个不同的java接口(interface),请问,它有没有vtable,
有几个,是怎样实现多态的.
在c++中,如果类C多重继承自两个不同的抽象类(类A和类B),那么类C中就会有
两个vtable,一个存放类A的虚函数指针,另一个存放类B的虚函数指针,
那么请问:
如果我的一个java类继承了两个不同的java接口(interface),请问,它有没有vtable,
有几个,是怎样实现多态的.
|
你用过java.lang.reflect这个包里的东西吗?
甚至于对各个厂商,实现是可能不一样的.你知道怎样用就行了.至少我是这样的.
甚至于对各个厂商,实现是可能不一样的.你知道怎样用就行了.至少我是这样的.
|
java没有虚函数的概念,java中所有的函数都是"虚"的,java不需要vtable来实现dynamic binding,因为它总是间接寻址的。
所以java没有c++语言中vtable的概念。
所以java没有c++语言中vtable的概念。
|
我认为(个人观点):
1.Java中对Interface不是继承,而是实现(implements);
2.Java中对借口的实现要求必须具体实现该借口的methods;
3.接口没有构造函数和析构函数的;
所以,我认为Java中没有多继承,只是使用interface对多继承进行模拟,但效果非常好。
--------------------------------------------
CSDN论坛助手很棒,希望以后更好,我坚决拥护!
1.Java中对Interface不是继承,而是实现(implements);
2.Java中对借口的实现要求必须具体实现该借口的methods;
3.接口没有构造函数和析构函数的;
所以,我认为Java中没有多继承,只是使用interface对多继承进行模拟,但效果非常好。
--------------------------------------------
CSDN论坛助手很棒,希望以后更好,我坚决拥护!
|
java实现多态,也是类似vtable那一套。
因为java是仿照C++设计的
因为java是仿照C++设计的
|
java中实现多态主要有两种方法:
1、重载,这个应该不要多说了。
2、覆盖,即子类定义的方法覆盖父类的方法,如下面的程序中,
import java.io.*;
public class Test
{
public static void main(String argsp[])
{
A a=new A();
B b=new B();
function(a);
function(b);
}
static void function(A a)
{
a.f();
}
}
class A
{
void f()
{
System.out.println("This is in class A.");
}
}
class B extends A
{
void f()
{
System.out.println("This is in class B.");
}
}
是B类中的方法f()覆盖A类中的f(),即,在对象b中,只有一个方法f(),即子类中的,所以不需要用vtable.
1、重载,这个应该不要多说了。
2、覆盖,即子类定义的方法覆盖父类的方法,如下面的程序中,
import java.io.*;
public class Test
{
public static void main(String argsp[])
{
A a=new A();
B b=new B();
function(a);
function(b);
}
static void function(A a)
{
a.f();
}
}
class A
{
void f()
{
System.out.println("This is in class A.");
}
}
class B extends A
{
void f()
{
System.out.println("This is in class B.");
}
}
是B类中的方法f()覆盖A类中的f(),即,在对象b中,只有一个方法f(),即子类中的,所以不需要用vtable.
|
blue_teeth (小小蓝牙) :
接口相当于C++的只有纯虚函数的纯抽象类。
你用C++试验一下就可以了。
另外 还可以参考一下COM的实现方法。
接口相当于C++的只有纯虚函数的纯抽象类。
你用C++试验一下就可以了。
另外 还可以参考一下COM的实现方法。
|
接口不是继承,根本不存在什么虚函数表的问题
接口和抽象类的设计意图本质不同
接口和抽象类的设计意图本质不同
|
我认为Java中的接口主要是为了实现C++中的多重继承。但同时又提供了一种比多重继承更灵活的一种实现。
Java中的接口将实现与方法完全分离,在接口中只提供一种约定,在真正的实现中可以根据约定,实现适合于自己的方法。
************************
我是Java的初学者,接触Java有三个月的吧,以前是学习VB的,提出的看法有许多不足,还请各位大侠多多指教,谢谢!
Java中的接口将实现与方法完全分离,在接口中只提供一种约定,在真正的实现中可以根据约定,实现适合于自己的方法。
************************
我是Java的初学者,接触Java有三个月的吧,以前是学习VB的,提出的看法有许多不足,还请各位大侠多多指教,谢谢!
|
faint.
Java当然有类似vtable的东西。否则怎么实现rtti, virtual function 啊?
不论implements还是extends, 对象模型上都是一样的。不过Java的实现更简单,当然没那么高效。
个人没有验证过,听一个教授说,Java用的是类似于hashtable的方法来检索虚函数的。当然,这样的hashtable一定在cache中。
仔细想想,应该是合理的。C++的vtable用offset, 比hashtable快。但问题是,对多重继承需要有多个vtable, 并且指针赋值有可能改变指针值。
如:
class D:public B1, B2{};
D* pd = new D;
B2* p = pd;
这里,隐含着一个指针offset的调整。
更讨厌的是:
还要检查pd是否为0, 如果是0,就不调整。相对于指针赋值这样的小操作,这可是很大的开销!
另外,允许一个指针指向不是对象开始的地方,对gc算法来说也是一个大挑战,即使是可能的话。
实现vtable一般有三种方法,
1. C++的方法,简单的offset。对多重继承可能要几个vtable. 指针赋值开销大。
2. java的方法,用hashtable. 一个vtable就够了。
3. 用offset, 但用涂色算法来决定offset(不是接口中第一个函数就一定在offset 0). 只要一个vtable, 没有offset调整,所以没有指针赋值的开销。也没有hashtable的开销。最快。问题是,编译程序必须知道整个类的hierarchy.象Java这样允许动态加载类的语言是不能用的。
Java当然有类似vtable的东西。否则怎么实现rtti, virtual function 啊?
不论implements还是extends, 对象模型上都是一样的。不过Java的实现更简单,当然没那么高效。
个人没有验证过,听一个教授说,Java用的是类似于hashtable的方法来检索虚函数的。当然,这样的hashtable一定在cache中。
仔细想想,应该是合理的。C++的vtable用offset, 比hashtable快。但问题是,对多重继承需要有多个vtable, 并且指针赋值有可能改变指针值。
如:
class D:public B1, B2{};
D* pd = new D;
B2* p = pd;
这里,隐含着一个指针offset的调整。
更讨厌的是:
还要检查pd是否为0, 如果是0,就不调整。相对于指针赋值这样的小操作,这可是很大的开销!
另外,允许一个指针指向不是对象开始的地方,对gc算法来说也是一个大挑战,即使是可能的话。
实现vtable一般有三种方法,
1. C++的方法,简单的offset。对多重继承可能要几个vtable. 指针赋值开销大。
2. java的方法,用hashtable. 一个vtable就够了。
3. 用offset, 但用涂色算法来决定offset(不是接口中第一个函数就一定在offset 0). 只要一个vtable, 没有offset调整,所以没有指针赋值的开销。也没有hashtable的开销。最快。问题是,编译程序必须知道整个类的hierarchy.象Java这样允许动态加载类的语言是不能用的。
|
java取消多重extends,是因为多重实现继承有语义上的问题。
class A{
void f(){...}
}
class B{
void f(){...}
}
class C extends A, B{
}
new C().f()有二义性。
当然,C++用c.A::f()和c.B::f()来区分。但Java不想把语言搞得没必要的复杂。
而且对以下的代码:
C c = new C();
A a = c;
a.f();
B b = c;
b.f();
同一个对象,调用同一个函数,却产生不同的结果。这样的语义是很丑陋的。
Java不能容忍这样的事发生, 因为在Java里,有这样的简单的invariant: 一个对象,不论它的静态类型是什么,对某一函数signature的调用永远都指向同一个函数体。
class A{
void f(){...}
}
class B{
void f(){...}
}
class C extends A, B{
}
new C().f()有二义性。
当然,C++用c.A::f()和c.B::f()来区分。但Java不想把语言搞得没必要的复杂。
而且对以下的代码:
C c = new C();
A a = c;
a.f();
B b = c;
b.f();
同一个对象,调用同一个函数,却产生不同的结果。这样的语义是很丑陋的。
Java不能容忍这样的事发生, 因为在Java里,有这样的简单的invariant: 一个对象,不论它的静态类型是什么,对某一函数signature的调用永远都指向同一个函数体。