30

ダイヤモンド問題に関するウィキペディア:

「...ダイヤモンドの問題は、2つのクラスBとCがAから継承し、クラスDがBとCの両方から継承するときに発生するあいまいさです.DのメソッドがAで定義されたメソッドを呼び出す場合(およびメソッドをオーバーライドしない場合) )、そして B と C がそのメソッドを異なる方法でオーバーライドした場合、どのクラスから継承しますか: B または C?"

したがって、ダイヤモンドは次のようになります。

  A
 / \
B   C
 \ /
  D

私の質問は、そのようなクラス A がなくても、B と C が同じメソッド、たとえば foo() を宣言するとどうなるかということです。これは同じ問題ではありませんか?なぜダイヤモンド問題と呼ばれるのですか?

例:

class B {
    public void foo() {...}
}

class C {
    public void foo() {...}
}

class D extends B, C {
}

new D().foo();
4

4 に答える 4

14

それは同じ問題ではありません。

元の問題では、オーバーライドされたメソッドを A から呼び出すことができます。あなたの問題では、存在しないため、これは当てはまりません。

ひし形の問題では、クラス A がメソッド Foo を呼び出すと衝突が発生します。通常はこれで問題ありません。しかし、クラス D では、Foo のどのインスタンスを呼び出す必要があるかを知ることはできません。

         +--------+
         |   A    |
         | Foo    |
         | Bar    |
         +--------+
            /  \
           /    \
          /      \
+--------+        +--------+
|   B    |        |   C    |
| Foo    |        | Foo    |
+--------+        +--------+
          \      /
           \    /
            \  /
         +--------+
         |   D    |
         |        |
         +--------+

あなたの問題では、メソッドを呼び出すことができる共通の祖先はありません。クラス D では、選択できる Foo の 2 つのフレーバーがありますが、少なくとも 2 つあることはわかっています。そして、あなたはどちらかを選ぶことができます。

+--------+        +--------+
|   B    |        |   C    |
| Foo    |        | Foo    |
+--------+        +--------+
          \      /
           \    /
            \  /
         +--------+
         |   D    |
         |        |
         +--------+

しかし、いつものように、多重継承は必要ありません。アグリゲーションとインターフェースを使用して、これらすべての問題を解決できます。

于 2010-01-14T14:49:53.597 に答える
11

ひし形の問題では、クラス D はクラス A から暗黙的に仮想メソッドを継承します。それを呼び出すには、クラス D は次のように呼び出します。

A::foo()

クラス B と C の両方がこのメソッドをオーバーライドする場合、実際に呼び出される問題が発生します。

ただし、2番目の例では、クラス D が呼び出されたものを明示的に指定する必要があるため、これは当てはまりません。

B::foo()
C::foo()

したがって、問題は実際には同じではありません。ダイヤモンドの問題では、派生クラスを参照していませんが、それらの基本クラスを参照しているため、あいまいです。

とにかく、それは私がそれを理解する方法です。

私は C++ のバックグラウンドを持っていることに注意してください。

于 2010-01-14T14:57:18.523 に答える