2016-07-19 7 views
0

меня это раздражает множественного наследования алмаз обреченности со сложным твист (мы говорим об объектах MS COM, деталь, которая будет актуальна позже) -C++ Алмазные Гибели с внешним SDK

  • Предположим абстрактный класс (интерфейс) A, который имеет некоторые чистые виртуальные методы.
  • Другой абстрактный класс (другой интерфейс) B получен из A и расширяет его с помощью более чистых виртуальных методов.
  • Класс C получен из класса A и реализует все его абстрактные методы.
  • класса D в настоящее время происходит от класса B, реализуя все абстрактные методы от А и В.

Сейчас у меня есть два класса C, D с большим количеством копий вставили кода (так как большинство из требуемый интерфейс находится в классе A). Я бы хотел избежать этого, наследуя D от C, однако D также наследует от B, что создает классический бриллиант с угрозой.

Я знаю, что это можно решить с помощью виртуального наследования, но вот поворот в сюжете: классы A и B являются COM-интерфейсами, определенными в SDK, который я не могу изменить (то есть «Ah» и «Bh» доступны только для чтения). Наследование от A до B не является виртуальным, и это не может быть изменено. Я могу изменять классы C и D, но они должны полностью придерживаться определенных интерфейсов.

Буду признателен за любые творческие идеи о том, как преодолеть это.

+1

Рассмотрите возможность использования композиции вместо. –

+0

Реальная проблема - это даже не «Алмаз судьбы». Вы имеете дело с COM, который имеет только одно наследование. Имея D наследовать от C перерывов, что независимо от того, как вы это делаете. – MSalters

+0

В конечном счете действительно используется композиция. Принудил мне написать прокси-функцию для каждой функции в A, но, по крайней мере, она сработала. – Dan

ответ

1

Я предполагаю из деталей вопроса, что проблема у вас есть с функциями, а не с некоторыми переменными-членами A (который, кажется, является просто интерфейсом).

В этом случае здесь есть два варианта, которые возникают на ум.

1) имеют D собственный C, а не наследуют его.

class D : public B 
{ 
    public: 
    virtual int FA() 
    { 
     return m_c.FA(); 
    } 
    private: C m_c; 
}; 

или наследовать приватно от C

class D : public B, private C 
{ 
    public: 
    virtual int FA() 
    { 
     return C::FA(); 
    } 
}; 

Где FA() есть некоторая чисто виртуальная функция в

Оба случая включают определение функции для реализации FA в D, но фактическая реализация детали не дублируются.

+0

Учитывая, что 'A' является интерфейсом Microsoft COM, мы знаем, что он не может иметь данные элемента. – MSalters

0

The ATL способ разрешения этой ситуации:

template <typename Itf> 
class IAImpl : public Itf { 
    // Implement IA methods 
}; 

class C : public IAImpl<IA> {}; 

class D : public IAImpl<IB> { 
    // Implement methods of IB that are in addition to IA. 
};