虚拟函数如何在C#和Java中运行?
它是否使用与C ++类似的相同vtable和vpointer概念,还是完全不同?
答案 0 :(得分:19)
编码采访者喜欢这个问题。是。尽管Java没有虚拟关键字,但Java具有虚函数,您可以编写它们。
在面向对象的编程中,virtual function或虚方法是一种函数或方法,其行为可以通过具有相同签名的函数在继承类中重写。这个概念是面向对象编程(OOP)的多态性部分中非常重要的一部分。
询问有关这种特定语言的架构问题需要很好的沟通技巧和对Java编译器基本原理的深入掌握,特别是接口,抽象类以及继承如何工作。
引导访问者了解虚拟功能的具体示例。
是的,您可以使用接口在Java中编写虚拟函数。
Java interface methods都是“纯虚拟”,因为它们被设计为被覆盖。例如:
interface Bicycle { //the function applyBrakes() is virtual because
void applyBrakes(); //functions in interfaces are designed to be
} //overridden.
class ACMEBicycle implements Bicycle {
public void applyBrakes(){ //Here we implementing applyBrakes()
System.out.println("Brakes applied"); //function, proving it is virtual.
}
}
是的,您可以使用抽象类在Java中编写虚函数。
Java Abstract classes包含隐式“虚拟”方法,由扩展它的类实现。例如:
abstract class Dog {
final void bark() { //bark() is not virtual because it is
System.out.println("woof"); //final and if you tried to override it
} //you would get a compile time error.
abstract void jump(); //jump() is a virtual function because it
} //is part of an abstract class and isn't
//final.
class MyDog extends Dog{
void jump(){
System.out.println("boing"); //here jump() is being overridden, a
} //demonstration that it is virtual.
}
public class Runner {
public static void main(String[] args) {
MyDog myDog = new MyDog(); //instantiating myDog
myDog.jump(); //calling the overridden function jump()
}
}
您可以通过使函数final
例如:
class myJavaFoobarClass {
final boolean giveMeTrueFunction() //this Java function is NOT virtual
{ //because final keyword prevents this
return true; //function from being modified in a
} //subclass.
boolean isItRainingFunction() //this Java function IS virtual because
{ //without the final keyword, the function
return false; //can be overridden in a subclass.
}
}
答案 1 :(得分:10)
至少Java中没有虚拟关键字。
它只是解析为你所调用的任何方法的派生版本......
class A{
void sayhi(){ System.out.println("A");}
}
class B extends A{
void sayhi(){ System.out.println("B");}
}
A a = new B();
a.sayhi();
将打印“B”。
您可以通过声明一个Abstract类并保留声明但未实现的纯虚方法来创建“纯虚拟”方法。或者使用interface / implements而不是class / extends。接口基本上是一个所有方法都是纯虚拟的类。这有一个额外的好处,即类可以实现多个接口,因为与C ++不同,Java类只能直接继承另一个类。
编辑:
回应你的评论,Naveen:
如果你说A a = new A(); a.sayhi();它会打印“A”。
java术语是动态的。您可以将其视为虚拟,但这可能会使某些Java开发人员感到困惑。那些不懂C ++的人,至少。在Java中没有明确的指针,因此我们不需要担心虚拟/非虚拟。没有VTable,您只需回溯该类及其祖先,直到找到所需方法的实现。只有单一的继承,所以你不必担心构造函数的顺序(它总是自下而上)。
在C ++中,如果您有虚拟方法并执行类似
之类的操作,则会得到不同的行为a->sayhi();
其中a是A *指向B的实例而不是
a.sayhi();
其中a是A类型的对象,其中包含B类型的对象
答案 2 :(得分:4)
在Java中,虚拟功能完全不同。在Java中,虚函数表示可以在其子类中重写的函数。所以Java的所有非静态方法都是虚函数。只有final和private函数不会被继承,因此它们不是虚函数。
所以我们可以说所有非final和private的非静态函数都是Java中的虚函数。
答案 3 :(得分:2)
支持多态的所有语言都使用vtable来解析对正确函数的方法调用。 Java和.NET也是如此。
它们都编译成一些中间语言(IL for .NET和java的字节代码),但vtable在这种中间语言中不可见。底层引擎(CLR for .NET)
支持它答案 4 :(得分:0)
我确信Java不使用vtables,因为它能够支持二进制兼容性。
澄清:vtable是在编译派生/子类时构建的。如果基类/超类布局发生变化,则需要重新编译d / s的vtable。在Java中,情况并非如此。您无需重新编译d / s即可更改b / s。
嗯。 vtable可能是在runt-time构建的。当类加载时。在这种情况下,Java和C ++会相同但不同。
答案 5 :(得分:-2)
纯虚函数在C ++中。 C#使用接口来实现相同的目的,所以我建议你走这条路。