Когда множественное наследование может быть единственным разумным решением? [закрыто]

Чтобы быть ясным, я не спрашиваю, является ли / почему множественное наследование хорошим или плохим. Я слышал много аргументов с обеих сторон этой дискуссии.

Мне интересно, существует ли какая-либо проблема проектирования или сценарий в C ++, в котором множественное наследование является либо единственным способом достижения чего-либо, либо, по крайней мере, является наиболее оптимальным способом по сравнению со всеми другими альтернативами до такой степени, что оно не будет смысл считать что-то еще.

Очевидно, что этот вопрос не относится к языкам, которые не поддерживают множественное наследование.

 Firas Assaad07 июл. 2009 г., 20:41
Аналогичный вопрос:stackoverflow.com/questions/573913/…

Ответы на вопрос(10)

Существует ситуация, в которой вы наследуете от класса и, возможно, реализуете один или два интерфейса в Java. Я думаю, это то, что вы бы решили с множественным наследованием в C ++.

istream а такжеostream оба родителиiostream, Так как они оба наследуют отios_baseАлмаз.

Это единственный «разумный» аргумент. решение в том смысле, что для потоковой части стандартных библиотек было бы неразумно занимать ту же самую линию, что и алгоритмы и коллекции. Таким образом, ostream ведет себя полиморфно, а не как «тип утка» интерфейс, такой как Iterator (*).

Как только у вас есть динамический полиморфизм, вам нужно множественное наследование для реализации более одного интерфейса одновременно.

(*) Предположительно, это потому, что все остальное будет рухнуть. Вы должны быть в состоянии написать реальные функции, которые управляют потоками, вместо того, чтобы заставлять пользователей иметь шаблоны повсюду. Это происходит потому, что обычно записывают в «некоторый поток», я не знаю, что до времени выполнения », но не хочу манипулировать« некоторым набором, я не знаю, что до времени выполнения ».

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

namespace Object_Database {
    class Object {
      public:
        virtual void store() ;
        virtual void fetch() ;
    };
}

namespace Reflectives {
    class Object {
      public:
        virtual std::vector<std::string> > membernames();
        virtual std::vector<std::string> > methodnames();
    };
}

Первая иерархия позволяет пользователям создавать объекты, которые можно сериализовать в базу данных объектов и из нее, и требует, чтобы все такие объекты были получены из класса Object_Database :: Object. Вторая иерархия позволяет пользователям создавать объекты, которые могут запрашиваться во время выполнения для имен их членов, и требует, чтобы все такие объекты были получены из Reflectives :: Object.

Если вам требуются объекты, которые могут выполнять обе задачи, вам просто нужно написать:

  class ReflectivePickle : 
  public Object_Database::Object, 
  public Reflectives::Object {
    // ...
  };

Другие решения неразумны.

behavior, не простоcontract, Однако, как демонстрируют другие языки, множественное наследование - не единственный способ решения этой проблемы за счет углубления вашего дерева наследования. Как таковые, сценарии, где выmust а такжеmay only Использовать множественное наследование было бы довольно редко.

Чтобы получить лучшее представление об ответе на этот вопрос. Идея интерфейса заключается в создании абстрактного класса, который действует как шаблон для другого класса. Преимущество здесь в том, что шаблоны могут быть объединены в конкретном классе. Например-

Родительский класс - FoodStore Подкласс - CoffeeShop Подкласс- Пекарня

С этим деревом наследования FoodStore может быть пекарней или кофейней, но не обоими. Но тогда что бы мы назвали Starbucks?

Лучший способ, IMO-

Родительский класс - FoodStore Интерфейс- CoffeeShop Интерфейс-Пекарня

Открытый класс Starbucks расширяет FoodStore реализует CoffeeShop, Bakery {...}

Вам нужно немного знать Java, чтобы понять это, но имейте это в виду. Интерфейсы довольно элементарные, ИМО.

В качестве дальнейшего размышления, возможно, интерфейсы разработаны так, чтобы подчиняться «не повторяйте себя». Очевидно, теперь, когда я это упомянул.

ия, посмотрите Eiffel. Они решают проблему алмазов с помощью переименования функций, что намного проще, чем разрешение областей, и даже поддерживает прямое повторное наследование, так что:

Наследовать B, B, B

когда возникает необходимость использовать этот тип наследования.

Их библиотека ядра имеет открытый исходный код, и множественное наследование широко используется, если вы хотите увидеть примеры.

http://sourceforge.net/projects/eiffelstudio/files/

Решение Вопроса

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

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

 07 июл. 2009 г., 21:33
@Jeff L: «Прокси»; класс в Java может быть использован в качестве обходного пути.
 Jeff L07 июл. 2009 г., 21:08
Означает ли это, что основанное на политике проектирование просто невозможно на таком языке, как Java, или есть способы обойти это?
 07 июл. 2009 г., 21:10
На самом деле, связанная статья указывает, что множественное наследование является лишь наиболее распространенным шаблоном реализации (с некоторыми существенными преимуществами), а не то, что оно абсолютно необходимо.
 07 июл. 2009 г., 21:33
Не так, как обычно работает дизайн на основе политик, я не думаю, что Java может это сделать. Можно было бы сделать альтернативу, где есть переменные-члены для каждой политики, а не наследование от нее, но это теряет некоторые преимущества, которые имеет наследование. Если Java вообще может использовать такие шаблоны, я не знаю.
 07 июл. 2009 г., 22:15
@GMan: При помощи небольшого количества стандартного Java-кода вы могли бы просто делегировать методы, известные во время кодирования (и, в частности, любые вызовы, которые фактически вызывает хост) объектам политики, и иметь для них средства доступа. В версии C ++ хост автоматически расширяет свой интерфейс для включения произвольных функций, желаемых пользователем и включаемых в их классы mixin. Поэтому я полагаю, что это зависит от того, считаете ли вы (или, по правде говоря, Александреску), что эта функция отделима от «шаблона политики»; как таковой или его неотъемлемой частью. В Java вы все еще можете разрешить пользователям восстанавливать объекты политики, downcast и call.

Using pure virtual base classes as "Interfaces", as in Java ( http://en.wikipedia.org/wiki/Interface_(Java) ), this is a very common O.O. pattern in all O.O. languages, not only Java

To do police-based design

Но также:

To compose a class with several mixins ( http://en.wikipedia.org/wiki/Mixin ); I consider this a very good use of multiple inheritance to achieve code reuse!

когда базовые классы являются «интерфейсными классами», то есть базовыми классами, где все методы являются чисто виртуальными, ни один из них не имеет реализаций [помните, что вы все еще можете определить реализацию, но вы должны вызывать ее явно], и нет данных членов. Очень похоже на «интерфейсы» в Java или (из того, что я слышу) C #.

Чтобы использовать полиморфизм в C ++, вы не можете использовать состав, вы должны использовать (публичное) наследование.

Поэтому, если класс Bar наследует (публично) от Printable и Serializable, я могу рассматривать объект как печатный объект, сериализуемый объект или объект Bar (используя указатели или ссылки).

С композицией вы не можете этого сделать.

Когда вы хотите наследовать функциональность, а не роль, показательный примерboost::noncopyable (другие языки, которые поддерживают это (в отличие от Java и C #), называют этоmixin).

Ваш ответ на вопрос