仮想関数は C# と Java でどのように機能しますか?
C++ と同じ vtable と vpointer の概念を使用していますか、それともまったく異なるものですか?
少なくとも Java には virtual キーワードはありません。
呼び出しているメソッドの最も派生したバージョンに解決されるだけです...
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 を宣言し、宣言されているが実装されていない純粋仮想メソッドを残すことにより、「純粋仮想」メソッドを作成できます。または、class / extends の代わりに interface / implements を使用します。インターフェイスは基本的に、すべてのメソッドが純粋仮想であるクラスです。これには、クラスが複数のインターフェースを実装できるという追加のボーナスがあります。これは、C++ とは異なり、Java クラスは他の 1 つのクラスのみを直接継承できるためです。
編集:
あなたのコメントに応えて、ナヴィーンは:
A a = new A(); と言った場合 a.sayhi(); 「A」を出力します。
Java 用語は動的です。仮想と考えることができますが、一部の Java 開発者は混乱する可能性があります。少なくとも C++ を知らない人。Java には明示的なポインターがないため、仮想/非仮想について心配する必要はありません。VTable はありません。必要なメソッドの実装が見つかるまで、クラスとその祖先をバックトラックするだけです。継承は単一であるため、コンストラクターの順序を気にする必要はありません (常にボトムアップです)。
C++では、仮想メソッドがあり、次のようなことをすると、異なる動作が得られます
a->sayhi();
ここで、a は A* であり、代わりに B のインスタンスを指していました
a.sayhi();
ここで、a はタイプ B のオブジェクトを保持するタイプ A のオブジェクトでした
Java では仮想関数はまったく異なります。Java では、仮想関数とは、そのサブクラスでオーバーライドできる関数を意味します。したがって、Java のすべての非静的メソッドは仮想関数です。final 関数と private 関数のみが継承されないため、仮想関数ではありません。
したがって、最終的でも非公開でもないすべての非静的関数は、Java では仮想関数であると言えます。
ポリモーフィズムをサポートするすべての言語は、vtables を使用してメソッド呼び出しを正しい関数に解決します。Java と .NET も同様です。
どちらもいくつかの中間言語 (.NET の場合は IL、Java の場合はバイト コード) にコンパイルされますが、この中間言語では vtable が表示されません。基盤となるエンジン (CLR for .NET) でサポートされています。
Java はバイナリ互換性をサポートできるため、vtables を使用しないと確信しています。
明確にするために:vtableは、派生/サブクラスがコンパイルされるときに構築されます。基本/スーパークラスのレイアウトが変更された場合、d/s の vtable を再コンパイルする必要があります。Java では、これは当てはまりません。d/s を再コンパイルせずに b/s を変更できます。
うーん。実行時に vtable が構築される可能性があります。クラスがロードされたとき。その場合、Java と C++ は同じですが、異なります。
純粋仮想関数は C++ にあります。C# はインターフェイスを使用して同じ目的を果たすため、その方法をお勧めします。