Существует несколько проблем с множественным наследованием, когда оно используется с полноценными классами, но все они вращаются вокруг неоднозначности .
Неоднозначность проявляется несколькими способами:
- Если у вас есть два базовых класса с одним
x
и тем же полем и запрашивается производный тип x
, что он получает?
- Если две
x
переменные имеют несовпадающие типы, вы можете сделать это.
- Если они одного типа, вы можете попытаться объединить их в одну переменную.
- Вы всегда можете выставить их как странные полностью определенные имена.
- Если у вас есть два базовых класса с одной и той же функцией
f
с одинаковыми сигнатурами, и кто-то вызывает f
, что вызывается ?
- Что если два базовых класса имеют другого общего виртуального предка (проблема с бриллиантами).
- Что если функция имеет разные, но совместимые подписи?
- Когда вы создаете класс с двумя базовыми классами, какой из конструкторов базовых классов вызывается первым? Когда вы уничтожаете объект, который убит?
- Когда вы размещаете объект в памяти, как вы делаете это последовательно?
- Как вы обрабатываете все эти случаи с 3 базовыми классами? 10?
И это игнорирует такие вещи, как динамическая диспетчеризация, вывод типов, сопоставление с образцом и другие вещи, о которых я знаю меньше, которые становятся более сложными, когда язык поддерживает множественное наследование полных классов.
Черты или Mix-In (или интерфейсы, или ...) - это все конструкции, которые специально ограничивают возможности типа, так что нет никакой двусмысленности. Они редко владеют чем-либо самим. Это позволяет сгладить состав типов, потому что нет двух переменных или двух функций ... есть переменная и ссылка; функция и подпись. Компилятор знает, что делать.
Другой распространенный подход - заставить пользователя «встраивать» (или смешивать) свой тип по одному. Вместо того, чтобы базовые классы были равноправными партнерами в новом типе, вы добавляете один тип к другому, переопределяя все, что там было (обычно с необязательным синтаксисом для переименования и / или повторного раскрытия переопределенных битов).
Есть ли что-то, что невозможно с миксином / признаком, но возможно с множественным наследованием в стиле C ++?
В зависимости от языка - обычно становится проблематичным или невозможным объединять реализации функций и хранилище для переменных из нескольких базовых классов и представлять их в производном типе.
Возможно ли столкнуться с проблемой алмазов с ними?
Иногда появляются менее серьезные изменения в зависимости от вашего языка, но обычно нет. Весь смысл черт состоит в том, чтобы сломать такую двусмысленность.