2

C ++:純粋仮想関数f()を持つ基本クラスAがあり、2つのクラスBとCが仮想的にAから継承し、クラスDがBとCの両方から継承します(典型的なダイアモンド構造):

   A f() = 0
 v/ \v
 B   C
  \ /
   D

次の場合、どこでいつf()= 0を実装する必要がありますか?

  1. BとCの両方に純粋仮想関数もあります(->抽象クラスは継承された純粋仮想を実装する必要がありますか?)
  2. それらの1つ(B XOR C)のみが純粋仮想関数を持っています(->もう1つはまだf()を実装する必要がありますか?)
  3. BもCも、独自の純粋な仮想を持っていません(-> BとCの実装をスキップして、Dに「パススルー」する方法はありますか?)
  4. 上記の3つのケースのうち、Dがf()を実装する必要があるのはどれですか?Dがオプションでf()を実装するのはどの場合ですか?その場合、もしあれば、Dがf()を実装することはできませんか?

この種の問題について他に一般的な提案はありますか?

ありがとう。

4

4 に答える 4

1

BとCの両方に純粋仮想関数もあります(->抽象クラスは継承された純粋仮想を実装する必要がありますか?)

はい 、継承されたすべての純粋仮想関数を実装するD 必要があります。 クラスがクラスのすべての純粋仮想関数を実装しない限り、クラス自体から派生し、抽象クラスとして機能します。

それらの1つ(B XOR C)のみが純粋仮想関数を持っています(->もう1つはまだf()を実装する必要がありますか?)

D任意の階層のBaseクラスを介して継承する純粋仮想関数を実装する必要があります。その直接のBaseクラスが純粋仮想関数を定義していない場合、そのクラスも抽象クラスになりD、継承された純粋仮想関数を実装しない限り、抽象クラスにもなります。

BもCも、独自の純粋な仮想を持っていません(-> BとCの実装をスキップして、Dに「パススルー」する方法はありますか?)

DA->B&を介して継承する純粋仮想関数を実装する必要があります。A-Cこの場合、とは両方ともB抽象Cクラスになることに注意してください。

上記の3つのケースのうち、Dがf()を実装する必要があるのはどれですか?Dがf()を実装するのはオプションですか?その場合、もしあれば、Dがf()を実装することはできませんか?

Dfoo()インスタンス化可能(非抽象)にできるようにするには、上記の3つの条件すべてで実装する必要があります。

結論:

  1. クラスは、基本クラスのすべてから継承するすべての純粋仮想関数を実装する必要があります。実装しないと、クラスは抽象クラスになります。
  2. 仮想属性は継承されます。スーパークラスが関数virtualを宣言する場合、派生クラスのオーバーライドされた関数も仮想であり、それから派生するすべてのクラスに仮想属性を渡します。

死のダイヤモンドを避けてください!あなたがそれに伴う微妙さを本当に理解していない限り。多くの人は、仮想継承を使用しようとしますが、それが実際には設計で達成したいことを達成するための最も適切な方法ではありません。一部のシナリオでは、仮想継承の使用が実際に必要ですが、それでも言語によって提供される重要な構成要素ですが、間違った方法で使用されることがよくあります。したがって、仮想継承が本当に必要かどうかを確認するために、一度設計を再検討することは理にかなっています。

以下は良い読み物かもしれません:

  1. 多重継承-パートI
  2. 多重継承-パートII
  3. 多重継承-パートIII
于 2011-09-16T15:42:16.247 に答える
0

BとCの両方に純粋仮想関数もあります(->抽象クラスは継承された純粋仮想を実装する必要がありますか?

はい。抽象クラスから継承されるクラスは、インスタンス化できるように仮想関数を実装する必要があります。そうでなければ、それらも抽象化されます。

それらの1つ(B XOR C)のみが純粋仮想関数を持っています(->もう1つはまだf()を実装する必要がありますか?)

からCも派生しているためA、も実装する必要がありますf()

BもCも、独自の純粋な仮想を持っていません(-> BとCの実装をスキップして、Dに「パススルー」する方法はありますか?)

出来るよ。しかし、それは-のようなインスタンス化BまたはC単独でのインスタンス化を防ぎます

A *obj = new B(); // Error
A *obj = new C(); // Error

上記の3つのケースのうち、Dがf()を実装する必要があるのはどれですか?Dがf()を実装するのはオプションですか?その場合、もしあれば、Dがf()を実装することはできませんか?

f()Dすべての親クラスを抽象化する必要がある限り、単独で実装できます。

于 2011-09-16T15:39:51.353 に答える
0

唯一の要件は、「リーフ」レベル(最も派生したレベル)ですべてに実装があることです(おそらく1つだけです。そうでない場合、グラフにアクセスした時点で、同じ「距離」でより多くの実装があると、あいまいさが生じる可能性があります。 "。

したがって、Dは、まだ実装されていないすべてを実装する必要があります。または、(曖昧さを解消するために)異なるパスを介してすべてが複数回実装されている必要があります。何か-Dレベルで-がまだ実装されていない場合...Dはインスタンス化できず、実装はDに要求され、EはDから派生します。

- ダイヤモンドは永遠に -

于 2011-09-16T15:50:05.350 に答える
0
  1. いいえ、抽象クラス(おそらくBC)は、継承された純粋な仮想を実装する必要はありません。ただし、のような子クラスDは、インスタンス化するためにそうする必要があります。

  2. いいえ、繰り返しますがBC純粋仮想メソッドを継承し、オーバーライドするだけで最終的な具象クラスを生成できます。

  3. Dはい、これは2つの方法のいずれかで実装を通過します。両方が仮想的に継承する場合はB、一度実装します。それらが仮想的に継承しない場合は、との両方のバージョンをオーバーライドして具体的にする必要があります。CDDBCf

  4. が抽象的である場合D、実装する必要はありませんf。具体的であると仮定すると、3つのケースすべてで、でオーバーライドする必要がありfますDBCオーバーライドの両方fD必要ない場合のみ。

デザインをよく見て、ダイヤモンドの継承を削除します。ほとんどの場合、これらすべての種類の問題を防ぐための最善の策はそれです。

于 2011-09-16T15:55:01.570 に答える