仮想機能とは
仮想関数は、スーパークラスで定義された関数であり、そのサブクラスが完全なクラス定義を持つためには、サブクラスに存在する必要があります。 仮想関数は、仮想継承と呼ばれるオブジェクト指向プログラミングパラダイムに依存しています。これは、C ++で「仮想」キーワードを使用して最も一般的に見られます。 仮想関数を定義するには、スーパークラスとサブクラスの2つのクラスが必要です。 スーパークラスは、関数が最初に宣言され、場合によっては定義される場所です。 サブクラスは、関数が定義されている場所です。つまり、関数がスーパークラスで定義されているかどうかによってオーバーライドされます。
仮想関数は、2つの方法のいずれかで定義できます。 まず、スタブとして定義できます。スタブでは、空のボディを持ち、何もしません。 次に、スーパークラスのヘッダーファイルでNULLとして定義されている純粋な仮想関数として定義できます。
両方の方法には長所と短所があります。 関数をスタブとして定義すると、何もしなくても、すべてのサブクラスにその実装が確実に含まれます。 ただし、関数をオーバーライドしてサブクラスに適切に実装することを忘れた場合、これを示すエラーや警告は表示されません。 一方、純粋な仮想関数を定義するには、各サブクラスに関数の独自の定義が必要であり、そうでない場合はエラーが表示されます。
ただし、仮想関数には非仮想関数と同じ継承ルールが適用されるため、3つ以上のレベルを持つ継承階層では、仮想関数の明示的な定義が必要ない場合があります。 たとえば、サブクラスBに実装されている仮想関数を宣言するクラスAを考えることができます。クラスBには独自のサブクラスであるクラスCがあります。クラスCは、継承するため、クラスAの関数の明示的な定義を必要としませんクラスBの定義。必要に応じて、クラスCはクラスBの機能をオーバーライドするか、クラスBの機能をオーバーライドすると同時に呼び出します。
他の極端な場合、仮想関数は、サブクラスで仮想と宣言されている場合、サブクラスで定義する必要はありません。 たとえば、仮想関数を宣言し、2つのサブクラスBとCを持つクラスAを考えることができます。さらに、クラスBにはサブクラスDとEがあり、サブクラスCにはサブクラスFとGがあると想像できます。
クラスBからGはすべて、何らかの方法で定義されたクラスAの仮想関数を持っている必要があります。 クラスBにAの関数の実装がある場合、クラスDとEはそれをやり直す必要はありません。 おそらくCのサブクラスはAの関数を実装する必要がありますが、両方とも異なることを行うため、クラスC自体で関数を定義することは有用ではありません。 その場合、関数はクラスCでvirtualとして宣言され、実装は必要ありません。
仮想関数は学習するのが困難な場合がありますが、適切に使用すると、コードの重複を減らし、コードを一般的に理解しやすくすることができます。 ただし、特に多重継承に関して、仮想関数には多くの落とし穴があります。 多重継承では、あいまいに定義された仮想関数が互いに競合する可能性があるため、そのコンテキストでは注意して使用する必要があります。