Специализация на двух классах-предках в C

#c #inheritance

#c #наследование

Вопрос:

Я определил абстрактный интерфейс, состоящий из трех классов:

 class rendering_context {…}
class window : public rendering_context {…}
class offscreen : public rendering_context {…}
  

Это позволяет различным клиентским объектам игнорировать тип контекста рендеринга, в котором они находятся. Пока все хорошо.

Затем я определил конкретные реализации:

 class sdl::window : public window {…}
class sdl::offscreen : public offscreen {…}
  

Все это работает так, как ожидалось, и клиентские классы довольны, не имея ни малейшего представления о том, основаны ли они на экране / вне экрана / SDL или нет.

Мое замешательство:

Теперь у меня есть специфичная для SDL функциональность, которая применяется во всех контекстах рендеринга, то есть не только в одном или другом из sdl::window or sdl::offscreen .

Это говорит о том, что класс sdl::rendering_context должен быть где-то извлечен, но как мне включить это в иерархию классов?

Если я создам конкретные классы следующим образом:

 class sdl::window : public window, public sdl::rendering_context {…}
class sdl::offscreen : public offscreen, public sdl::rendering_context {…}
  

И предполагая sdl::rendering_context , что наследуется от rendering_context then разве я не унаследовал от rendering_context twice неявно? Делает ли это тот факт, что rendering_context в данном случае это абстрактный базовый класс без членов и нескольких чисто виртуальных функций, это нормально?

Это то же самое, что и проблема с бриллиантами? Похоже, что это может быть, но разница в том, что нет никакой двусмысленности в отношении того, какой метод базового класса вызывать: они чисто виртуальные, и это, безусловно, будет конкретная реализация в нижней части иерархии, которая выполняется на практике.

[Примечание: Ни одно из моих объявлений классов на самом деле не похоже на приведенное выше, это просто для иллюстрации иерархии. Текущий код компилируется и работает, он просто дублирует некоторые функции.]

Комментарии:

1. Прочитав несколько советов по лучшей практике, возможно, это неправильный вопрос? Должен ли я вместо этого повторно использовать sdl::rendering_context код через композицию и оставить иерархию классов исключительно для определения интерфейсов?

2. Этот вопрос больше подходит для programmers.stackexchange.com .

3. Спасибо, да, я согласен. Написав вопрос, я понимаю, что это больше касается моего общего подхода к определению интерфейса и повторному использованию кода, а не конкретной технической проблемы.

4. Вот переделка вопроса о программистах StackExchange: programmers.stackexchange.com/questions/246273 /…

Ответ №1:

И если предположить, что sdl ::rendering_context наследуется от rendering_context, то разве я не унаследовал от rendering_context дважды неявно?

Если это проблема, вы можете рассмотреть виртуальное наследование, в котором rendering_context используется общий базовый класс. Если вы хотите сделать это:

 class window : public virtual rendering_context {...}
class offscreen : public virtual rendering_context {...}
  

Комментарии:

1. Понял, да, это работает, спасибо. Знаете ли вы, есть ли последствия для производительности виртуального базового класса, когда он чисто виртуальный?