Почему я должен избежать множественного наследования в C++?

Предупреждение: недопустимое смещение строки 'XXX'

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

Пример:

$var = "test";
echo $var["a_key"];

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

160
задан Gerald 18 December 2014 в 06:50
поделиться

11 ответов

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

Сводка

  1. Полагает, что состав функций, вместо наследования
  2. опасаться Ромба Страха
  3. Рассматривают наследование нескольких интерфейсов вместо объектов
  4. Иногда, Множественное наследование является правильной вещью. Если это, то используйте его.
  5. быть готовым защитить Ваш несколько - наследованная архитектура в обзорах кода

1. Возможно, состав?

Это верно для наследования, и таким образом, это еще более верно для множественного наследования.

Делает Ваш объект, действительно должен наследоваться от другого? Car не должен наследоваться Engine для работы, ни Wheel. Car имеет Engine и четыре Wheel.

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

2. Ромб Страха

Обычно, у Вас есть класс A, тогда B, и C оба наследовались от A. И (не спрашивают меня, почему) кто-то тогда решает, что D должен наследоваться и от [1 111] и C.

я встретился с этим видом проблемы дважды за 8 лет восьмерок, и забавно видеть из-за:

  1. , Каким количеством из ошибки это было с начала (В обоих случаях, D не должен был наследоваться и от [1 114] и от C), потому что это было плохой архитектурой (на самом деле, C не должен был существовать вообще...)
  2. , Сколько специалисты по обслуживанию оплачивали это, потому что в C++, родительский класс A присутствовал дважды в его классе D внука, и таким образом, обновляя одно родительское поле A::field, предназначенное, любое обновление его дважды (до [1 120] и C::field), или наличие чего-то идет тихо неправильно и катастрофический отказ, позже (новый указатель в [1 122], и удалите C::field...)

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

В Иерархии объектов, необходимо попытаться сохранить иерархию как Дерево (узел имеет ОДНОГО родителя), не как график.

[еще 1161] о Ромбе (редактируют 03.05.2017)

настоящей проблеме с Ромбом Страха в C++ ( принятие дизайна является звуковым - рассмотрели Ваш код! ), то, что необходимо сделать выбор :

  • он желательный для класса A для существования дважды в расположении, и что это означает? Если да, то любой ценой наследовались ему дважды.
  • , если это должно существовать только однажды, затем наследуйтесь ему фактически.

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

, Но как все полномочия, с тем питанием прибывает ответственность: Рассмотрите Ваш дизайн.

3. Интерфейсы

Множественное наследование нуля или реальных классов, и нуля или большего количества интерфейсов обычно Хорошо, потому что Вы не встретитесь с Ромбом Страха, описанного выше. На самом деле это - то, как вещи сделаны в Java.

Обычно, то, что Вы имеете в виду, когда C наследовался от [1 125] и B, - то, что пользователи могут использовать C, как будто это было A, и/или как будто это было B.

В C++, интерфейс является абстрактным классом, который имеет:

  1. весь его метод, объявленный чистым виртуальный (снабженный суффиксом = 0) <глоток> (удалил 03.05.2017)
  2. никакие членские переменные

, Множественное наследование нуля к одному реальному объекту, и нуля или большего количества интерфейсов не считают "вонючим" (по крайней мере, не так).

[еще 1162] об Интерфейсе Краткого обзора C++ (редактируют 03.05.2017)

Первый, шаблон NVI может использоваться для создания интерфейса, потому что реальные критерии не должны иметь никакого состояния (т.е. никакие членские переменные, кроме [1 130]). Точка Вашего абстрактного интерфейса должна опубликовать контракт ("можно назвать меня этим путем и этим путем"), ничто больше, ничто меньше. Ограничение наличия только абстрактного виртуального метода должно быть проектным решением, не обязательством.

11103-секундный, в C++, имеет смысл наследоваться фактически абстрактным интерфейсам, (даже с дополнительной стоимостью/косвенностью). Если Вы не сделаете, и интерфейсное наследование появляется несколько время в Вашей иерархии, то у Вас будут неоднозначности.

В-третьих, объектная ориентация является большой, но это не Единственная Истина Там <глоток> ТМ в C++. Используйте правильные инструменты, и всегда помните, что у Вас есть другие парадигмы в C++, предлагающем другой вид решений.

4. Вам действительно нужно Множественное наследование?

Иногда, да.

Обычно, Ваш C класс наследовался от [1 132] и B, и A, и B два несвязанных объекта (т.е. не в той же иерархии, ничем общем, различных понятиях, и т.д.).

, Например, у Вас могла быть система [1 136] с X, Y, Z координаты, которые в состоянии сделать, много геометрических вычислений (возможно, точка, часть геометрических объектов) и каждый Узел является Автоматизированным Агентом, который в состоянии связываться с другими агентами.

, Возможно, у Вас уже есть доступ к двум библиотекам, каждому с его собственным пространством имен (другая причина использовать пространства имен... Но Вы используете пространства имен, не так ли?), один являющийся geo и другой являющийся ai

, Таким образом, у Вас есть свое собственное own::Node, происходят и от [1 140] и geo::Point.

Это - момент, когда необходимо спросить себя, если Вы не должны использовать состав вместо этого. Если own::Node будет действительно действительно и ai::Agent и geo::Point, то состав не сделает.

Тогда Вам будет нужно множественное наследование, имение Вашего own::Node связывается с другими агентами согласно их положению в 3D пространстве.

(Вы отметите, что ai::Agent и geo::Point полностью, полностью, ПОЛНОСТЬЮ НЕ СВЯЗАНЫ... Это решительно уменьшает опасность множественного наследования)

Другие случаи (отредактируйте 03.05.2017)

существуют другие случаи:

Иногда можно использовать состав, и иногда MI лучше. Точка: у Вас есть выбор. Сделайте это ответственно (и рассмотрите Ваш код).

5. Так, я должен сделать Множественное наследование?

Большую часть времени, по моему опыту, нет. MI не является правильным инструментом, даже если это, кажется, работает, потому что это может использоваться ленивым для укладки функций вместе, не осознавая последствий (как создание Car и Engine и Wheel).

, Но иногда, да. И в то время, ничто не будет работать лучше, чем MI.

, Но потому что MI является вонючим, быть готовым защитить Вашу архитектуру в обзорах кода (и защита хорошо, потому что, если Вы не в состоянии защитить его, тогда Вы не должны делать этого).

253
ответ дан Community 23 November 2019 в 21:29
поделиться

требуется включенного 4/8 байта за класс. (Один этот указатель в классе).

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

0
ответ дан Ronny Brendel 23 November 2019 в 21:29
поделиться

Можно использовать состав в предпочтении к наследованию.

общее настроение - то, что состав лучше, и он очень хорошо обсужден.

0
ответ дан Ali Afshar 23 November 2019 в 21:29
поделиться

Вне схемы размещения алмазов множественное наследование имеет тенденцию делать объектную модель тяжелее для понимания, который в свою очередь увеличивает затраты на обслуживание.

Состав внутренне легко понять, постигать, и объяснить. Это может стать утомительным для записи кода для, но хороший IDE (это были несколько лет, с тех пор как я работал с Visual Studio, но конечно IDE Java у всех есть большие инструменты автоматизации ярлыка состава) должен получить Вас по тому препятствию.

кроме того, с точки зрения обслуживания, "ромбовидная проблема" подходит в нелитеральных экземплярах наследования также. Например, если у Вас есть A и B, и Ваш класс C расширяет их обоих, и A имеет 'makeJuice' метод, который делает апельсиновый сок, и Вы расширяете это для создания апельсинового сока со скручиванием извести: что происходит, когда разработчик для 'B' добавляет 'makeJuice' метод, который генерирует и электрический ток? И 'B' могут быть совместимые "родители" прямо сейчас , но это не означает, что они всегда будут так!

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

1
ответ дан Tom Dibble 23 November 2019 в 21:29
поделиться

Использование и Злоупотребления Наследованием.

статья делает отличную работу по объяснению наследования, и это - опасности.

1
ответ дан csexton 23 November 2019 в 21:29
поделиться

Необходимо использовать его тщательно, существуют некоторые случаи, как Ромбовидная проблема , когда дела могут идти сложные.

alt text
(источник: learncpp.com )

2
ответ дан Glorfindel 23 November 2019 в 21:29
поделиться

Вы не должны "избегать" множественного наследования, но необходимо знать о проблемах, которые могут возникнуть, такие как 'ромбовидная проблема' ( http://en.wikipedia.org/wiki/Diamond_problem ) и рассматривать питание, данное Вам с осторожностью, как Вы должны со всеми полномочиями.

6
ответ дан jwpfox 23 November 2019 в 21:29
поделиться

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

"Mixins" также иногда полезны. Они - вообще маленькие классы, обычно не наследовавшиеся ничему, обеспечивая полезную функциональность.

, пока иерархия наследования довольно мелка (как это должно почти всегда быть), и хорошо управляемый, Вы вряд ли получите страшное ромбовидное наследование. Ромб не является проблемой со всеми языками, которые используют множественное наследование, но обработка C++ его является часто неловкой и иногда озадачивающей.

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

8
ответ дан David Thornley 23 November 2019 в 21:29
поделиться

См. w: Множественное наследование .

Множественное наследование получило критику и как таковой, не реализован на многих языках. Критические замечания включают:

  • Увеличенная сложность
  • семантическая неоднозначность, часто получаемая в итоге как ромбовидная проблема .
  • Неспособность явно наследоваться многократно единому классу
  • Порядок наследования, изменяющего семантику класса.

Множественное наследование на языках с C++ / конструкторы стиля Java усиливает проблему наследования конструкторов и конструктора, объединяющего в цепочку, таким образом, создавая обслуживание и проблемы расширяемости на этих языках. Объекты в отношениях наследования со значительно переменными способами строительства трудно реализовать при конструкторе, объединяющем парадигму в цепочку.

современный способ разрешить это для использования интерфейса (чистый абстрактный класс) как интерфейс COM и Java.

я могу сделать другие вещи вместо этого?

Да, Вы можете. Я собираюсь украсть от GoF.

  • Программа к Интерфейсу, не Реализация
  • Предпочитают состав по наследованию
11
ответ дан Eugene Yokota 23 November 2019 в 21:29
поделиться

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

самый большой, являющийся ромбом смерти:

class GrandParent;
class Parent1 : public GrandParent;
class Parent2 : public GrandParent;
class Child : public Parent1, public Parent2;

у Вас теперь есть две "копии" GrandParent в Ребенке.

C++ думал об этом, хотя и позволяет Вам сделать виртуальное наследование для обхождения проблем.

class GrandParent;
class Parent1 : public virtual GrandParent;
class Parent2 : public virtual GrandParent;
class Child : public Parent1, public Parent2;

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

38
ответ дан billybob 23 November 2019 в 21:29
поделиться

От интервью с Bjarne Stroustrup :

Люди вполне правильно говорят, что Вам не нужно множественное наследование, потому что что-либо, что можно сделать со множественным наследованием, которое можно также сделать с единичным наследованием. Вы просто используете прием делегации, который я упомянул. Кроме того, Вам не нужно никакое наследование вообще, потому что что-либо, что Вы делаете с единичным наследованием, которое можно также обойтись без наследования путем передачи через класс. На самом деле Вам не нужны никакие классы также, потому что можно сделать все это с указателями и структурами данных. Но почему Вы хотели бы сделать это? Когда удобно использовать средства языка? Когда Вы предпочли бы обходное решение? Я видел случаи, где множественное наследование полезно, и я даже видел случаи, где довольно сложное множественное наследование полезно. Обычно я предпочитаю использовать средства, предлагаемые языком выполнению обходных решений

141
ответ дан Nemanja Trifunovic 23 November 2019 в 21:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: