Этот макет не реализуется на C++, даже с дополнительным классом помощи.
Тот факт, что этот B наследуется от A, и вы хотите разделить наследование A с C на одной стороне и с D на другом, требует, чтобы B, C и D фактически наследовались от A. Но тогда A будет разделенных по обоим ветвям вашего алмаза.
Альтернативы
Какие альтернативы могут быть?
Если бы удалось сломать обмен А между левой и правой ветвей ваших алмазов, вы бы также сломать обмен общей базы.
Если бы ввести некоторые промежуточные классы А1, А2 для реализации левой и правой доли в своих отраслях, вы бы, но застрял на то, что оба B должны наследовать либо один, либо другой
единственный выход мог бы иметь дубликат класс для В.
Это последнее решение не выполнить ваше требование, но будет выглядеть следующим образом:
struct Base { int x; };
struct A : public virtual Base { int a; };
struct AC : public A{}; // synonym
struct B : public virtual A { int b; };
struct BC : public virtual AC { int b; }; // !! clone !!
struct C : public virtual AC { int c; };
struct D : public virtual A { int d; };
struct E : public BC, C { int e; };
struct F : public B, D { int f; };
struct Final : public E, F { };
А вот доступ к ЧЛЕНАМ:
Final f;
f.x = 2; // unambiguous: there's onely one of it
f.f = 1;
f.e = 2;
f.d = 3;
f.c = 4;
//f.b = 5; // ambiguous: there are two of it
f.E::b = 5; // successful desambiguation
f.F::b = 6; // successfuldesambiguation
//f.a = 7; // ambiguous: there are two of it
f.E::a = 7; // successful desambiguation
f.F::a = 8; // successful desambiguation
Чтобы вернуться к вашей постановке задачи: вы говорите, что не можете вмешиваться выше E и F.В этом случае ваши варианты очень ограничены:
- вы публично наследовать
- вы в частном порядке наследования через несколько промежуточных классов
Но эффект был бы тот же общий доступ к, как и следующий код desmonstrates (на в верхней части приведенной выше):
class FI : private F // make F private
{ public:
void set_xa(int u, int v) { x = u; a= v; }
void show_xa() { cout << "x:" << x << " a:" << a << endl; }
};
class EI : private E // make E private
{
public:
void set_xa(int u, int v) { x = u; a = v; }
void show_xa() { cout << "x:" << x << " a:" << a << endl; }
};
struct Final3 : public EI, public FI { };
Final3 h;
h.EI::set_xa(3, 4);
h.FI::set_xa(5, 6);
h.EI::show_xa();
h.FI::show_xa();
// the shared virtually inherited memebers are still shared !
Вывод:
С наследованием вы полностью связаны дизайном выше E и F, на который вам не разрешено влиять.
Так что первые вопросы будут:
- вы не можете изменить эту конструкцию после всех (т.е. клонирование одного B)?
- не было бы неприемлемо, если бы между двумя ветвями была A, а может быть, есть веская причина?
Если вы отвечаете не на оба вопроса, вам придется пойти на композиции, а также осуществлять своего рода proxy design pattern, где ваш объект, состоящий является прокси для обоих компонентов.
Можете ли вы создать шаблон 'A'? – curiousguy
Предположим, что смогу. Что бы это изменило? Класс B также должен был бы решить, какую специализацию A он хотел бы наследовать. –
Если вы можете изменить имена классов (шаблон - это просто способ изменить имена классов), вы можете решить свои ограничения 'template class B : public virtual A {' –
curiousguy