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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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 {
    // ...
  };

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

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

Потоки C ++ используют множественное наследование:istream а такжеostream оба родителиiostream, Так как они оба наследуют отios_baseАлмаз.

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

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

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

Как уже было сказано на других ответах:

Но также:

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

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

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

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

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

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

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

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

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

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

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

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

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

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