Подтвердить что ты не робот

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

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

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

Ответ 3

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

Ответ 4

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

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

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

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

Ответ 5

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

Родительский класс - FoodStore Подкласс-CoffeeShop Подкласс-Хлебобулочные изделия

С этим деревом наследования FoodStore может быть Bakery или CoffeeShop, но не тем и другим. Но тогда мы бы назвали Starbucks?

Лучший способ, ИМО -

Родительский класс - FoodStore Интерфейс - CoffeeShop Интерфейс - Хлебобулочные изделия

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

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

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

Ответ 6

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

Ответ 7

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

  • Использование чистых виртуальных базовых классов как "интерфейсов", как в Java (http://en.wikipedia.org/wiki/Interface_ (Java)), это очень распространенный OO шаблон во всех O.O. языки, а не только Java

  • Чтобы сделать дизайн на основе полиции

Но также:

  • Чтобы создать класс с несколькими миксинами (http://en.wikipedia.org/wiki/Mixin); Я считаю это очень хорошим использованием множественного наследования для повторного использования кода!

Ответ 8

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

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

Другие решения необоснованны.

Ответ 9

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

Чтобы использовать полиморфизм в С++, вы не можете использовать композицию, вы должны использовать (общедоступное) наследование.

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

С составом вы не можете этого сделать.

Ответ 10

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

A наследует B, B, B

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

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

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