より適切な質問は、「なぜ C# には非仮想メソッドがあるのですか?」ということかもしれません。または、少なくとも、非仮想としてフラグを立てるオプションを備えたデフォルトで仮想ではないのはなぜですか?
C++ には、(Brian が非常にうまく指摘したように) 必要ない場合は料金を支払わないという考えがあります。問題は、あなたがそれを欲しがる場合、これは通常、鼻からお金を払うことを意味するということです. ほとんどの Java 実装では、多くの仮想呼び出し用に明示的に設計されています。vtable の実装は高速になる傾向があり、非仮想呼び出しよりもほとんど高価ではありません。つまり、非仮想関数の主な利点が失われます。さらに、JIT コンパイラは実行時に仮想関数をインライン化できます。そのため、効率上の理由から、実際に非仮想関数を使用する理由はほとんどありません。
したがって、それは主に最小の驚きの原則に帰着します。これは、すべてのメソッドが同じように動作することを示しており、半分が仮想で半分が非仮想ではありません。このポリモーフィズムを実現するには、少なくともいくつかの仮想メソッドが必要なので、それらをすべて仮想にするのは理にかなっています。さらに、同じ署名を持つ 2 つのメソッドを持つことは、自分自身を撃つことを求めているだけです。
ポリモーフィズムは、オブジェクト自体がその動作を制御する必要があることも規定しています。その動作は、クライアントがそれを FooParent と考えるか FooChild と考えるかによって決定されるべきではありません。
編集:だから、私は自分の主張について呼ばれています。この次の段落は私の推測であり、事実の記述ではありません。
これらすべての興味深い副作用は、Java プログラマーがインターフェースを非常に頻繁に使用する傾向があることです。仮想メソッドの最適化により、インターフェイスのコストが本質的に存在しないようになるため、ArrayList の代わりに (たとえば) List を使用し、後で単純な 1 行の変更で LinkedList に切り替えることができます。追加のペナルティなし。
編集: また、いくつかのソースをポニーします。元の情報源ではありませんが、Sun が HotSpot の仕組みについて説明しています。
インライン化
V テーブル