12

メソッドの静的バインディングの C++ の性質により、これはポリモーフィック呼び出しに影響します。

ウィキペディアから:

このディスパッチ メカニズムに関連するオーバーヘッドは低いですが、言語が対象とするように設計された一部のアプリケーション領域では、依然として重要な場合があります。このため、C++ の設計者である Bjarne Stroustrup は、動的ディスパッチをオプションで非デフォルトにすることを選択しました。virtual キーワードで宣言された関数のみが、オブジェクトのランタイム タイプに基づいてディスパッチされます。他の関数は、オブジェクトの静的タイプに基づいてディスパッチされます。

だからコード:

Polygon* p = new Triangle;
p->area();

がChild クラスにあるParent クラスarea()non-virtual関数である場合、上記のコードは、開発者が期待していない可能性のある を呼び出します。(導入した static-binding のおかげです)overriddenParent's class method

他の人が使用するクラス (ライブラリなど) を作成したい場合、そのような以前のコードが期待どおりに実行されるように、すべての関数を仮想にする必要がありますか?

4

5 に答える 5

26

簡単な答えは、実行時のポリモーフィズムのためにクラスの関数をオーバーライドするvirtual場合は、意図しない場合ではなく、それらをとしてマークする必要があるということです。

virtual柔軟性が増すと感じたからといって関数にマークを付けるのではなく、インターフェイスを公開するためのデザインと目的を考えてください。例:クラスが継承されるように設計されていない場合、メンバー関数を仮想化すると誤解を招く可能性があります。この良い例は、継承されることを意図していないため、仮想デストラクタを持たない標準ライブラリコンテナです。

すべてのメンバー関数を仮想としてマークしない理由、パフォーマンスのペナルティ、非PODクラスタイプなどを引用する理由はありませんが、クラスが実行時のオーバーライドを目的としていることを本当に意図している場合は、それが目的です。それとその周りといわゆる欠陥を超えて。

于 2011-11-28T15:35:29.570 に答える
3

派生クラスがそのメソッドをオーバーライドできるようにする必要がある場合は、仮想としてマークします。それはそれと同じくらい簡単です。

于 2011-11-28T15:33:36.470 に答える
2

原則として、クラスが基底クラスとして使用されるように明示的に設計されており、その関数がオーバーライドされるように設計されている場合にのみ、関数を仮想としてマークする必要があります。実際には、ほとんどの仮想関数は基本クラスで純粋仮想になります。また、オーバーライド関数のコントラクトを明示的に提供しない呼び出し反転の場合を除いて、仮想関数はプライベート (または最大限に保護) であり、コントラクトを強制する非仮想関数でラップする必要があります。

于 2011-11-28T17:18:31.390 に答える
1

メモリのパフォーマンスに関しては、何かが仮想である場合は仮想ポインター テーブルを取得するため、それを調べる 1 つの方法は、「1 つください、すべてください」です。それ以外の場合は、他の人が言うように、基本クラスでそのメソッドを呼び出すと特殊なバージョンが実行されるようにオーバーライドできるようにする場合は、それらを仮想としてマークします。

于 2011-11-28T15:40:36.180 に答える
0

それが基本的な考え方です。実際、親クラスを使用している場合は、すべてのメソッドをオーバーライドする必要はないと思うのでvirtual、このように使用すると思われる場合は作成してください。

于 2011-11-28T15:27:29.373 に答える