Ответ 1
Интерфейсы COM скорее похожи на интерфейсы JAVA - у них нет данных. Это означает, что наследование интерфейса отличается от наследования классов при использовании множественного наследования.
Для начала рассмотрим не виртуальное наследование с помощью шаблонов наследования в форме алмаза...
- B наследует A
- C наследует A
- D наследует B и C
Экземпляр D содержит два отдельных экземпляра элементов данных A. Это означает, что когда указатель-A указывает на экземпляр D, он должен определить, какой экземпляр A внутри D он означает - указатель различается в каждом случае, а указатели-указатели не являются простыми релябельными типами - также изменяется адрес.
Теперь рассмотрим тот же алмаз с виртуальным наследованием. Экземпляры B, C и D содержат один экземпляр A. Если вы считаете, что B и C имеют фиксированный макет (включая экземпляр A), это проблема. Если макет Bs [A, x] и макет Cs [A, y], тогда [B, C, z] недействителен для D - он будет содержать два экземпляра A. То, что вы должны использовать, это что-то вроде [ A, B ', C', z], где B '- все, начиная с B, кроме унаследованных A и т.д.
Это означает, что если у вас есть указатель-на-B, у вас нет единой схемы разыменования элементов, унаследованных от A. Поиск этих членов различается в зависимости от того, указывает ли указатель на чисто-B или B-in-D или B-in-something-else. Компилятору требуется некоторый ключ времени выполнения (виртуальные таблицы), чтобы найти унаследованные-из-членов. В конечном итоге вам понадобится несколько указателей на несколько виртуальных таблиц в экземпляре D, поскольку они являются vtable для унаследованного B и для унаследованного C и т.д., Что подразумевает некоторые издержки памяти.
Одиночное наследование не имеет этих проблем. Макет памяти экземпляров остается простым, а виртуальные таблицы также проще. Поэтому Java запрещает множественное наследование для классов. В наследовании интерфейсов нет элементов данных, поэтому снова эти проблемы просто не возникают - нет проблемы с унаследованным-A-с-D и разными способами найти A-in-B в зависимости от того, что этот конкретный B оказывается, внутри. Оба COM и Java могут допускать множественное наследование интерфейсов без необходимости обработки этих осложнений.
ИЗМЕНИТЬ
Я забыл сказать - без членов данных нет реальной разницы между виртуальным и не виртуальным наследованием. Однако с Visual С++ макет, вероятно, отличается, даже если нет элементов данных - с использованием одинаковых правил для каждого стиля наследования, независимо от того, присутствуют ли какие-либо элементы данных.
Кроме того, макет COM-памяти соответствует макету Visual-С++ (для поддерживаемых типов наследования), потому что он был разработан для этого. Нет причин, по которым COM не мог быть разработан для поддержки множественного и виртуального наследования "интерфейсов" с данными. Microsoft могла бы спроектировать COM для поддержки той же модели наследования, что и С++, но не выбрала - и нет причин, по которым они должны были сделать иначе.
Ранний код COM часто записывался на языке C, а это означало рукописные макеты структур, которые должны были точно соответствовать макету Visual С++ для работы. Макеты для множественного и виртуального наследования - ну, я бы не стал добровольно делать это вручную. Кроме того, COM всегда был своей собственностью, предназначенный для связи кода, написанного на разных языках. Это никогда не предназначалось для привязки к С++.
ПОЛУЧИТЬ БОЛЬШЕ РЕДАКТИРОВАНИЯ
Я понял, что пропустил ключевой момент.
В COM единственная проблема с макетом, которая имеет значение, - это виртуальная таблица, которая должна обрабатывать только отправку методов. Существуют значительные различия в макете в зависимости от того, принимаете ли вы виртуальный или не виртуальный подход, аналогично расположению объекта с элементами данных...
- Для не виртуальных Dttab содержит A-in-B vtab и A-in-C vtab.
- Для виртуальных A только один раз встречается внутри Ds vtable, но объект содержит несколько vtables, а указатели-указатели нуждаются в изменениях адреса.
С интерфейсом-наследованием это в основном реализация - существует только один набор реализаций методов для A.
В не виртуальном случае две копии виртуальной таблицы A будут идентичны (приводя к тем же реализациям метода). Его немного большая виртуальная таблица, но накладные расходы на объект меньше, а указатели-указатели - это только переименование типа (без изменения адреса). Это более простая и эффективная реализация.
COM не может обнаружить виртуальный случай, потому что нет никакого индикатора в объекте или vtable. Кроме того, нет смысла поддерживать обе конвенции, когда нет данных. Он просто поддерживает одно простое соглашение.