2015-06-02 1 views
1

Я ищу полезный пример множественного наследования в C++ и нашел пример для Window-creation здесь: A use for multiple inheritance? и немного изменил его. Он концептуально выглядит следующим образом:может ли абстрактный класс наследовать от «нормального» класса?

class Window 
class Skinable // abstract 
class Draggable // abstract 
class DraggableSkinnableWindow : Window, Draggable, Skinnable 

Я думаю, что это хороший пример, где ИМ имеет смысл. Так как не имеет смысла реализовывать класс Skinable, он должен быть определен абстрактным.

Теперь: Как это будет выглядеть, если я не буду использовать концепцию МИ. я бы использовал простую иерархическую структуру, как это:

class Window 
class Dragable : public Window 
class Skinable : public Dragable 
class DraggableSkinnableWindow : Skinnable 

Я все еще хочу Dragable и Skinable быть абстрактно, как хорошо, но это вообще возможно? Является ли второй пример хорошим решением для одного и того же контекста, но не с использованием ИИ?

Спасибо заранее!

+3

Да, абстрактные классы могут даже содержать полные реализации, и все же быть абстрактными. Вы определяете абстракцию, которую вы считаете неполной, но неполной не означает полностью лишенной субстанции. – StoryTeller

+1

Ваша идея с одним наследством звучит концептуально неправильно. Я могу представить перетаскиваемые элементы GUI, кроме целых окон (то же самое для скинов) – deviantfan

+0

Если язык не предоставляет MI, это обычно решается с помощью реализации интерфейсов. –

ответ

1

В то время как ваш пример является надежным прецедентом для множественного наследования, я не согласен с утверждением, что для Skinnable не имеет реализации. Скорее, поскольку @devianfan упоминается в его комментарии, ваша единственная альтернатива наследования не позволяет моделировать концептуальную таксономию.

Речь идет о перекрестных осевых классификациях. Окно является обтягивающим и перетаскиваемым, но ни одно из этих качеств не зависит.

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

1

Я думаю, что это хороший пример, где MI имеет смысл.

Это происходит, поскольку Window, Draggable, Skinnable не имеют общего предка, по крайней мере, кроме чистого абстрактного, в противном случае вам понадобится виртуальное наследование.

Поскольку не имеет смысла реализовывать класс Skinable, его следует определить абстрактно.

Это может иметь смысл, например, определить свойство skin + сеттеры и геттеры. Вы, кажется, запутывает аннотация классов и чистый аннотация классов. Абстрактные классы имеют хотя бы одну чистую виртуальную функцию, а это значит, что вы не можете их создать. Чистые абстрактные классы не имеют никакой реализации какого-либо метода, они содержат только чистые виртуальные функции и часто используются как концепция интерфейса реализации в C++.

Как бы это выглядело, если бы я не использовал концепцию МИ. Является ли второй пример хорошим решением для одного и того же контекста, но не с использованием ИИ?

Вы не можете сделать это правильно. C++ не проводит различия между классами и интерфейсами (так как это не дает такой концепции на уровне языка). Это то же самое, что удаление дескрипторов java или C#. Было бы возможно, если бы вы предоставили все соединения вручную, т. Е. Skinnable, Draggable оснований, произвели бы SkinnableDraggable и/или DraggableSkinnable (которые, вероятно, были бы эквивалентными). Это довольно убийца.

Ваш пример, как упоминалось выше, полностью смешивает несвязанные понятия. Например. Ваши Draggable s и Skinnable s должны быть Windows es. Это не очевидно и, конечно, не совсем правильно.

+0

«Вы не можете сделать это правильно. C++ не проводит различия между классами и интерфейсами». Это утверждение неверно. C++ позволяет классу наследовать от произвольного числа классов.Напротив, интерфейсы Java и C# разделяют версии абстрактных классов C++. Хотя концепция интерфейса, формализованная на языковом уровне, семантически обогащается, C++ не ограничивается с точки зрения реализации этого шаблона. –

+0

Я не уверен, к какому утверждению вы обращаетесь. «Вы не можете сделать это правильно». - Ну, вы не можете дать множественное наследование, не так ли? Это была предпосылка вопроса. «* C++ не различает классы и интерфейсы *». Я считаю, что сделал то же самое, что и вы. 1. Он не формализован. 2. Он использует 'class' для реализации концепции, я привел ABC в качестве примера. Не виртуальные интерфейсы также используют классы. Это две наиболее популярные реализации интерфейсов в C++. Если вы скажете, что можете сделать это без ИМ, я бы хотел увидеть пример. – luk32

+0

C++ имеет полную поддержку множественного наследования. https://ideone.com/Ou5AQe –

1

я бы, вероятно, пойти, как этот

class Window 
class Draggable : public virtual Window 
class Skinnable : public virtual Window 
class DraggableSkinnableWindow : Draggable, Skinnable 

и обеспечить реализацию по умолчанию в чисто виртуальных методов, содержащихся в Draggabel и Skinnable отдельно

class Draggable : public virtual Window { 

    virtual void aMethod() = 0; 
    void aMethodDefaultImplementation() = { //...// }; 
} 

затем внутри DraggableSkinnable у вас есть два варианта:

virtual void aMethod() = { aMethodDefaultImplementation() }; 

или

virtual void aMethod() = {// ...non-default implementation... //}; 

Это имеет преимущество обеспечения реализации по умолчанию, если вам нужен (как будто aMethod не чисто виртуальные), но заставляет вас просить, что явно (потому что это чисто виртуальная).

+0

Зачем вам делать что-либо «Skinnable» или «Draggable» в «Window», кажется сильным предположением. – luk32

+0

Это просто показалось мне целью OP. –

+0

Я так не думаю. У вас все еще есть множественное наследование, и вы вводите конкретизации (что больше похоже на «SkinnableWindow»). Конечно, это может быть разумно, я просто не вижу его, однако вы это делаете, и я вполне мог бы ошибаться =) – luk32