以下のコードで、コンパイラPureAbstractBase
が のあいまいな基本クラスであると不平を言うのはなぜMultiplyInheritedClass
ですか? PureAbstractBase
inとMultiplyInheritedClass
thatの 2 つのコピーがあり、それらがひし形の中央の行であるため、仮想的に派生する必要があることに気付きました (実際、以下のコードの問題を解決しています)。しかし、インターフェイスのコピーが 2 つあるにもかかわらず、 のコードが両方をオーバーライドして、 で定義されたインターフェイス クラスを明確に選択しないのはなぜですか?FirstConreteClass
SecondConreteClass
MultiplyInheritedClass
MultiplyInheritedClass
#include <iostream>
using namespace std;
class PureAbstractBase {
public:
virtual void interface() = 0;
};
// I know that changing the following line to:
// class FirstConcreteClass : public virtual PureAbstractBase {
// fixes the problem with this hierarchy
class FirstConcreteClass : public PureAbstractBase {
public:
virtual void interface() { implementation(); }
private:
void implementation() { cout << "This is object FirstConcreteClass\n"; }
};
// I know that changing the following line to:
// class SecondConcreteClass : public virtual PureAbstractBase {
// fixes the problem with this hierarchy
class SecondConcreteClass : public PureAbstractBase {
public:
virtual void interface() { implementation(); }
private:
void implementation() { cout << "This is object SecondConcreteClass\n"; }
};
class MultiplyInheritedClass : public FirstConcreteClass,
public SecondConcreteClass {
public:
virtual void interface() { implementation(); }
private:
void implementation() { cout << "This is object MultiplyInheritedClass\n"; }
};
さらに、次の階層で問題が発生しないのはなぜですか? この場合、ConcreteHandler クラスには AbstractTaggingInterface のコピーが 3 つありませんか? では、なぜ上記の例と同じ問題が発生しないのでしょうか?
#include <iostream>
using namespace std;
class AbstractTaggingInterface {
public:
virtual void taggingInterface() = 0;
};
class FirstAbstractHandler : public AbstractTaggingInterface {
public:
virtual void taggingInterface() { cout << "FirstAbstractHandler\n"; }
virtual void handleFirst() = 0;
};
class SecondAbstractHandler : public AbstractTaggingInterface {
public:
virtual void taggingInterface() { cout << "SecondAbstractHandler\n"; }
virtual void handleSecond() = 0;
};
class ThirdAbstractHandler : public AbstractTaggingInterface {
public:
virtual void taggingInterface() { cout << "ThridAbstractHandler\n"; }
virtual void handleThird() = 0;
};
class ConcreteHandler : public FirstAbstractHandler,
public SecondAbstractHandler,
public ThirdAbstractHandler {
public:
virtual void taggingInterface() = { cout << "ConcreteHandler\n"; }
virtual void handleFirst() {}
virtual void handleSecond() {}
virtual void handleThird() {}
};
最近同僚と話をしたところ、データ メンバーなしで純粋な仮想クラス (インターフェイス) から継承する場合、仮想継承は必要ないと主張したため、これらすべてについて頭を悩ませようとしています。前者のコード例が機能せず、後者が機能する理由を理解することは、これを頭の中で理解するのに大いに役立つと思います(そして、彼のコメントが正確に何を意味していたのかを明確にします)。前もって感謝します。