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

аюсь понять, как COM определяет макет своих объектов, чтобы клиент, который хочет использовать объект COM, знал, как это сделать.

Я читал, что COM-объект, который реализует несколько интерфейсов, может делать это по-разному, в том числе используя вложенные классы или множественное наследование.

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

Поэтому мой конкретный вопрос: есть ли разница в разметке памяти для объектов c ++, реализованных с использованием множественного наследования по сравнению с вложенными классами.

И кто-нибудь может указать мне, где указана компоновка COM-объекта?

 что он хочет и нуждается, - это таблица указателей на функции, когда он вызывает`IUnknown::QueryInterface()`, Как вы реализуете это полностью зависит от вас. MFC использует вложенные классы, почти все, что использует встроенную поддержку множественного наследования в компиляторе C ++. То, как компилятор MSVC ++ реализует его, полностью совместимо с тем, что нужно COM. Это не случайно. Используйте стандартный код, который вы видите в книгах о COM, который показывает, как правильно реализовать IUnknown.



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



 указанная в COM, - это vtable (таблица указателей виртуальных функций), связанная с каждым интерфейсом. Каждый интерфейс является производным от IUnknown, поэтому любой интерфейс объекта, на который имеет указатель клиент, может вызвать QueryInterface, чтобы получить другой интерфейс для того же объекта.

Для объектов нет обязательного макета. Действительно, вся идея объекта в COM сильно отличается от экземпляра класса в языке OO: единственный способ узнать, предоставляются ли два интерфейса одним и тем же объектом COM, - это вызвать QueryInterface для интерфейса IUnknown на обоих из них - если и только если они возвращают один и тот же указатель интерфейса, они являются интерфейсами одного и того же объекта.

Это довольно гибкая идея:

Например, возможно, чтобы COM-объекты загружали в память только часть своего внутреннего состояния: другие части их состояния могут быть лениво загружены / распределены, когда запрашиваются дополнительные интерфейсы.Состояние COM-объекта может быть распределено по нескольким несмежным областям памяти.

 что один интерфейс COM может иметь множественное наследование, но класс может реализовать несколько интерфейсов через множественное наследование. Таким образом, компоновка множественного наследования не имеет значения - каждый интерфейс будет иметь уникальную компоновку, и компилятор должен предоставить указатель на правильную компоновку.

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

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