Виртуальное наследство и ужасный бриллиант

Мне тяжело приходится с ужасной алмазной проблемой. Напоминаю, что вот классическая иерархия классов этой проблемы:

    B
   / \
 C1   C2
   \ /
    D

Для ее решения стандартным решением является заставить C1 и C2 использовать виртуальное наследование для наследования от B.

Моя проблема в том, что B и C1 происходят от B. SDK, который я не могу изменить. Пример ниже, где я не могу заставить SubClassBвиртуально наследоваться от Base. Классы: PureVirtualBase, Base и SubClassB взяты из SDK, который я использую. Я не могу их изменить. SubClassA и Leaf — мои пользовательские классы. Я могу изменить их.

     PureVirtualBase(SDK)
           |
        Base(SDK)
       /        \
 SubClassA   SubClassB(SDK)
       \        /
          Leaf

В такой ситуации, когда SubClassBнельзя изменить для использования виртуального наследования от Base. Как это должно быть, чтобы:

  • экземпляр Leafсодержал только один Base
  • избегал двусмысленности при попытке доступа к функциям, определенным чисто виртуальным в PureVirtualBaseи реализованным в Base
class PureVirtualBase
{
public:
    PureVirtualBase()
    {
        cout<<"<<PureVirtualBase::PureVirtualBase" << endl;
        cout<<">>PureVirtualBase::PureVirtualBase" << endl;
    }
    virtual int f_PureVirtualBase()=0;
};
class Base : public PureVirtualBase
{
public:
    Base(std::string id) {
        cout<<"<<Base::Base:"<<id << endl;
        m_id=id;
        cout<<">>Base::Base:"<<m_id << endl;
    }
    virtual int f_PureVirtualBase() {
       cout<<"Base::f_PureVirtualBase" << endl;
       return 1;
    }
private:
    std::string m_id;
};
class SubClassA:  public virtual Base
{
public:
    SubClassA(): Base("From SubClassA") {
        cout<<"<<SubClassA::SubClassA" << endl;
        cout<<">>SubClassA::SubClassA" << endl;
    }
};
class SubClassB:  public Base
{
public:
    SubClassB():Base("From SubClassB") {
        cout<<"<<SubClassB::SubClassB" << endl;
        cout<<">>SubClassB::SubClassB" << endl;
    }
};    
class Leaf:  public SubClassA, public SubClassB
{
public:
    Leaf():SubClassA(),  SubClassB(), Base("From Leaf") {
        cout << "<<Leaf::Leaf" << endl;
        cout << ">>Leaf::Leaf"<< endl;
    }
};
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    Leaf myleaf;
    myleaf.f_PureVirtualBase();
    return a.exec();
}
  • Если я прокомментирую вызов f_PurevirtualBase, он скомпилируется, но у меня будет предупреждение, что виртуальная база «База» недоступна в «Листе» из-за двусмысленностиЕсли я раскомментирую этот вызов: я получаю эту ошибку: запрос члена 'f_PureVirtualBase' неоднозначен
  • Если я добавлю к этому вызову префикс имени класса (мой лист.SubClassA::f_PureVirtualBase() работает, но что-то очевидно неверно, так как в Leafсодержится 2 Base. Объект).

Есть намек?

Дополнительная информация для ответа на комментарии

Моя целевая архитектура немного сложнее, чем образец, который я предоставил в исходном вопросе:

 PureVirtualBase(SDK)
       |
     Base(SDK)
        |
        --SubClassA
        --SubClassB(SDK)
        --SubClassC(SDK)
        --SubClassD(SDK)

LeafOne: наследуется от SubClassA и SubClassB (SDK)

LeafTwo: наследуется от SubClassA и SubClassC(SDK)

LeafThree: наследуется от SubClassA и SubClassD(SDK)

SubClassA — это мой собственный код. Он предоставляет пользовательские функции. Методы SDK должны обрабатывать его как базовый экземпляр. Этот класс не будет создан, но он здесь, чтобы иметь возможность обрабатывать LeafOne, LeafTwo и LeafThree одновременно при выполнении некоторой обработки.

10
задан Jonathan Leffler 13 March 2015 в 01:40
поделиться