我正在开发针对面向对象语言的编译器,该语言针对我编写的虚拟机,我将其用作跨平台抽象层。我对继承方法的工作方式感到困惑。可以说我有以下几行C#代码。
class myObject : Object {
public int aField;
public override string ToString() {
return "Dis be mah object";
}
public void regularMethod() { }
}
Object test = new myObject();
Console.WriteLine(test.ToString());
现在这将输出'Dis be mah object'。如果我调用regularMethod,但编译后的代码实际上会做这样的事情:
struct myObject {
public int aField;
}
public static void regularMethod(ref myObject thisObject)
{
}
编译后如何处理继承的方法ToString?编译器无法完成我在上面使用regularMethod所做的操作,因为如果确实如此,那么只有在创建myObject类型而不是普通的Object类型时才会返回'Dis be mah object'。我的猜测是struct myObject将包含一个函数指针/委托,它将在创建新实例时分配。
答案 0 :(得分:1)
如果您正在处理静态重载,那很简单:在处理代码时绑定到正确的实现。
但是,如果您正在使用动态重载,则必须在运行时决定事情。为此,您需要使用真实对象类型动态分派。这与使用方法重写完成的相同。
动态调度与后期绑定不同。在这里,您正在选择一个实现而不是您的操作的名称(尽管这个绑定将在编译时发生,但实现只会在运行时发生)。
静态地,您只能绑定到对象的声明类型的实现。它是在编译时完成的。
您可以使用一些机制来实现动态调度,它将决定您的语言范例。
您的语言是否已键入?弱打字?
例如,C ++提供了我提到的两种类型的调度。对于动态的(我相信是你感兴趣的那个),它使用虚拟表来为一个类进行映射。该类的每个实例都将指向一个指向该vtable的指针。vtable(一个用于同一类的所有对象)将具有所有动态绑定方法的地址。在进行呼叫时,将从该表中获取其中一个地址。类型兼容的对象具有地址的表,所有地址都具有相同的偏移量。
希望我帮助过。