18

関連する質問をいくつか見ましたが、これとまったく同じではありません...

クラスはいくつかの主要なカテゴリに当てはまるものとして扱ってきましたが、簡単にするために次の 4 つとしましょう。

  • いくつかのデータと一連の操作を持つ値クラス。それらはコピーされ、同等かどうか意味のある比較ができます (コピーは を介し​​て同等であると予想されます==)。 これらにはほとんどの場合、仮想メソッドがありません。

  • 割り当てとコピーを無効にする ID を持つインスタンスを持つ一意のクラス。operator==オブジェクトとしてではなくポインターとして比較するため 、通常、これらにはありません。ポインターまたは参照によってそれらを渡すことを余儀なくされているため、のリスクがないため、これらには非常に多くの仮想メソッドがあります。

  • Unique-but-Clonable Classesコピーを無効にしますが、それが本当に必要な場合はクローン作成をサポートするように事前に設計されています。 これらには仮想メソッドがあり、最も重要なのは、仮想構築/クローニングイディオムに従うものです

  • 保持しているもののプロパティを継承する コンテナ クラス。これらには仮想メソッドがない傾向があります...たとえば、「STL コンテナーに仮想デストラクタがないのはなぜですか?」を参照してください。.

この非公式な信念体系を保持しているにもかかわらず、私は何度か、コピー可能なものに仮想メソッドを追加しようとしました。「これができたらカッコイイ」と思っていたのに、どうしても壊れてしまう。

これにより、仮想メソッドを持ち、コピーを無効にしない型の実際の良い例を誰かが持っているのではないかと思いました。

4

4 に答える 4

6

ポリモーフィック クラスをコピーできることには、本質的に問題はありません。問題は、非リーフ クラスをコピーできることです。オブジェクトのスライスはあなたを得るでしょう。

従うべき良い経験則は、具象クラスから決して派生しないことです。このように、非リーフ クラスは自動的にインスタンス化できないため、コピーできなくなります。ただし、安全のために、それらの割り当てを無効にしても害はありません。

もちろん、仮想関数を介してオブジェクトをコピーしても問題はありません。この種のコピーは安全です。

通常、ポリモーフィック クラスは「値クラス」ではありませんが、実際に発生します。std::stringstream頭に浮かぶ。コピー可能ではありませんが、(C++11 では) 移動可能であり、スライスに関して移動はコピーと同じです。

于 2013-12-01T06:55:39.713 に答える
3

仮想ディスパッチは実行時に発生します。それが必要な唯一の理由は、オブジェクトの実際の動的な型が実行時までわからない場合です。プログラムを作成するときに目的の動的な型が既にわかっている場合は、別の非仮想手法 (テンプレートや非ポリモーフィック継承など) を使用してコードを構造化できます。

実行時型付けの必要性の良い例は、I/O メッセージの解析、またはイベントの処理です。何らかの方法で、正しい具象型を選択するための何らかの大きなスイッチ テーブルを用意するか、次のように記述します。基本的にポリモーフィズムを再発明する独自の登録およびディスパッチシステム、または単に仮想ディスパッチを使用します。

(警告を挿入させてください: 多くの人が仮想関数を必要としない問題を解決するために誤用しています。それらは動的ではないためです。用心し、目に見えるものに批判的になりましょう。)

これにより、関数インターフェイスやコンテナーなどで、コードが主にポリモーフィックな基本クラスを処理することが明らかになりました。それでは、質問を言い換えてみましょう: そのような基本クラスはコピー可能であるべきですか? 実際の最も派生した基本オブジェクト (つまり、基本クラスは本質的に抽象的) は決してないので、これは実際には問題ではなく、その必要もありません。すでに「クローン」イディオムについて言及しましたが、これはポリモーフィックでのコピーの適切な類似物です。

現在、「クローン」機能は必ずすべてのリーフ クラスに実装されており、必然的にリーフ クラスのコピーが必要です。そうです、複製可能な階層のすべてのリーフ クラスは、仮想関数コピー コンストラクターを持つクラスです。また、派生クラスのコピー コンストラクターはそのベース サブオブジェクトをコピーする必要があるため、すべてのベースもコピー可能である必要があります。

したがって、問題を 2 つの可能性のあるケースに絞り込んだと思います。クラス階層内のすべてが完全にコピーできないか、階層がcloningをサポートしているため、必然的にその中のすべてのクラスがコピー可能になります。

では、仮想関数を持つクラスにはコピー コンストラクターが必要ですか? 絶対。(これは元の質問に答えます。クラスを複製可能なポリモーフィックな階層に統合すると、それに仮想関数が追加されます。)

ベース参照からコピーを作成する必要がありますか? おそらくそうではありません。

于 2013-12-02T09:33:22.157 に答える