Вам необходимо виртуальное наследование, чтобы преодолеть неоднозначность алмаза:
class FirstConcreteClass : public virtual PureAbstractBase { ... };
class SecondConcreteClass : public virtual PureAbstractBase { ... };
Длинное объяснение: предположим, у вас есть:
// *** Example with errrors! *** //
struct A { virtual int foo(); };
struct B1 : public A { virtual int foo(); };
struct B2 : public A { virtual int foo(); };
struct C: public B1, public B2 { /* ... */ }; // ambiguous base class A!
int main() {
A * px = new C; // error, ambiguous base!
px->foo(); // error, ambiguous override!
}
Наследование виртуальной функции foo
неоднозначно, поскольку оно происходит тремя способами: с B1
, с B2
и с A
. Диаграмма наследования образует «ромб»:
/-> B1 >-\
A-> ->C
\-> B2 >-/
Делая виртуальное наследование struct B1 : public virtual A;
и т. Д., Вы позволяете любому базовому классу C*
вызывать правильный член:
struct A { virtual int foo(); };
struct B1 : public virtual A { virtual int foo(); };
struct B2 : public virtual A { virtual int foo(); };
struct C: public B1, public B2 { virtual int foo(); };
Мы должны также определить C::foo()
, чтобы это имело смысл, поскольку в противном случае C
не будет иметь четко определенного члена foo
.
Еще несколько подробностей: предположим, что теперь у нас есть правильно виртуально наследуемый класс C
, как указано выше. Мы можем получить доступ ко всем различным виртуальным членам по желанию:
int main() {
A * pa = new C;
pa->foo(); // the most derived one
pa->A::foo(); // the original A's foo
B1 * pb1 = new C;
pb1->foo(); // the most derived one
pb1->A::foo(); // A's foo
pb1->B1::foo(); // B1's foo
C * pc = new C;
pc->foo(); // the most derived one
pc->A::foo(); // A's foo
pc->B1::foo(); // B1's foo
pc->B2::foo(); // B2's foo
pc->C::foo(); // C's foo, same as "pc->foo()"
}
Обновление: Как говорит Дэвид в комментарии, важным моментом здесь является то, что промежуточные классы B1
и B2
наследуются практически так, что другие классы (в данном случае C
) могут наследовать от их при одновременном сохранении наследства от A
однозначно. Извините за первоначальную ошибку и спасибо за исправление!