Існує ряд проблем із багаторазовим успадкуванням, коли він використовується з повноцінними класами, але всі вони обертаються навколо неоднозначності .
Неоднозначність проявляється кількома різними способами:
- Якщо у вас є два базових класи з одним
x
і тим же полем , і похідний тип запитує x
, що він отримує?
- Якщо обидві
x
змінні мають невідповідні типи, ви можете це зробити.
- Якщо вони одного типу, ви можете спробувати об'єднати їх у одну змінну.
- Ви завжди можете викрити їх як дивні цілком кваліфіковані імена.
- Якщо у вас є два базових класи з однаковою функцією
f
з однаковими підписами, і хтось дзвонить f
, хто отримує виклик?
- Що робити, якщо два базових класи поділяють іншого загального віртуального предка (проблема алмазів).
- Що робити, якщо функція має різні, але сумісні підписи?
- Коли ви будуєте клас з двома базовими класами, який із конструкторів базових класів називається першим? Коли ви знищуєте об'єкт, який вбивають?
- Коли ви викладаєте об'єкт в пам'ять, як це робити послідовно?
- Як ви вирішуєте всі ці випадки за допомогою 3 базових класів? 10?
І це ігнорує такі речі, як динамічна диспетчеризація, умовивідведення типу, відповідність шаблонів та інші речі, про які я знаю менше, які стають складнішими, коли мова підтримує багатократне успадкування повних класів.
Риси чи мікшн (або інтерфейси, або ...) - це всі конструкції, які конкретно обмежують можливості типу, щоб не було двозначності. Вони рідко самі володіють чим-небудь. Це дозволяє складності типів проходити більш гладко, оскільки немає двох змінних або двох функцій ... є змінна та посилання; функція та підпис. Компілятор знає, що робити.
Інший поширений підхід полягає в тому, щоб змусити користувача "будувати" (або змішувати) свій тип по черзі. Замість того, щоб базові класи були рівними партнерами нового типу, ви додаєте один тип до іншого - переосмислюючи все, що там було (як правило, з необов'язковим синтаксисом для перейменування та / або повторного викриття перезаписаних бітів).
Чи є щось, що неможливо за допомогою комбінацій / ознак, але можливо з багатократним успадкуванням у стилі C ++?
Залежно від мови - зазвичай стає проблематичним або неможливим об'єднати реалізацію функцій та зберігання змінних з декількох базових класів та викрити їх у похідному типі.
Чи можна зіткнутися з алмазною проблемою з ними?
Іноді менш чіткі варіанти з’являться на основі вашої мови, але зазвичай ні. Вся суть рис полягає в тому, щоб порушити таку неоднозначність.