3

クロスプラットフォームの抽象化レイヤーとして使用している仮想マシンを対象としたオブジェクト指向言語のコンパイラを開発しています。継承されたメソッドがどのように機能するかについて、私はちょっと混乱しています。次の 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 を使用して上記で行ったことを実行できませんでした。実行した場合、「Dis be mah object」は myObject 型の作成時にのみ返され、プレーンな Object 型では返されないためです。私の推測では、構造体 myObject には、新しいインスタンスが作成されたときに割り当てられる関数ポインター/デリゲートが含まれていると思います。

4

1 に答える 1

1

静的なオーバーロードを扱っている場合、それは非常に簡単です。コードを処理するときに正しい実装にバインドします。

ただし、動的オーバーロードを使用している場合は、実行時に決定する必要があります。このためには、実際のオブジェクト タイプを使用して動的ディスパッチを使用する必要があります。これは、メソッドのオーバーライドで行われるのと同じことです。

動的ディスパッチは遅延バインディングと同じではありません。ここでは、操作の名前ではなく実装を選択しています (このバインディングはコンパイル時に発生しますが、実装は実行時にのみ発生します)。

静的には、オブジェクトの宣言された型の実装にのみバインドします。これはコンパイル時に行われます。

動的ディスパスを実現するために使用できるいくつかのメカニズムは、言語パラダイムに影響します。

あなたの言語は入力されていますか?型付けが弱い?

たとえば、C++ では、前述の 2 種類のディスパッチが提供されます。動的なもの (あなたが興味を持っているものだと思います) の場合、仮想テーブルを使用して 1 つのクラスのマッピングを行います。そのクラスの各インスタンスは、その vtable へのポインタを持ちます。

  • 実装中

vtable (同じクラスのすべてのオブジェクトの 1 つ) には、動的にバインドされたすべてのメソッドのアドレスが含まれます。呼び出しが行われると、これらのアドレスの 1 つがこのテーブルから取得されます。型互換性のあるオブジェクトには、互換性のあるすべてのクラスのメソッドに対して同じオフセットを持つアドレスを持つテーブルがあります。

私が助けたことを願っています。

于 2013-06-15T02:54:15.070 に答える