2010-06-13 7 views
5

Я пытаюсь понять this example code относительно объектов-помощников браузера.Как реализовать несколько COM-интерфейсов на C++?

Внутри автор реализует один класс, который предоставляет несколько интерфейсов (IObjectWithSite, IDispatch).

Его функция QueryInterface выполняет следующие операции:

if(riid == IID_IUnknown) *ppv = static_cast<BHO*>(this); 
else if(riid == IID_IObjectWithSite) *ppv = static_cast<IObjectWithSite*>(this); 
else if (riid == IID_IDispatch) *ppv = static_cast<IDispatch*>(this); 

Я узнал, что с точки зрения C, указатели интерфейса являются лишь указатели на виртуальные таблицы. Поэтому я считаю, что C++ способен возвращать VTable любого реализованного интерфейса, используя static_cast.

Означает ли это, что класс, построенный таким образом, имеет кучу VTables в памяти (IObjectWithSite, IDispatch и т. Д.)? Что делает C++ с коллизиями имен на разных интерфейсах (каждый из них имеет функцию QueryInterface, AddRef и Release), могу ли я реализовать различные методы для каждого из них?

ответ

6

Да, существует несколько виртуальных таблиц, по одному для каждого унаследованного интерфейса. Static_cast <> возвращает его. Компилятор обеспечивает совместное использование общих методов в наследуемых интерфейсах, он заполняет каждый слот v-таблицы указателем на ту же функцию. Поэтому вам нужна только одна реализация AddRef, Release, QueryInterface. Только то, что вы хотите. Ничего из этого не случилось.

Это проблема только в том случае, когда в coclass реализованы несколько интерфейсов с тем же методом, что и вы не хотите дать ту же реализацию. Метод IConnectionPoint :: Advise() - это печально известный пример. Или это DAdvise()? К сожалению, я не помню, с чем она столкнулась, и как она была решена, она была покрыта ATL Internals. Очень хорошая книга кстати.

+1

Спасибо! Я сделал некоторые чтения самостоятельно, и я обнаружил, что он не только создает разные VTables, но также создает функции «thunk» для исправления указателя перед перенаправлением обратно на общую функцию. – Martin

3

В множественного наследования, множественные виртуальные таблицы расположены в определенной последовательности, как следующий формат, если данный this указатель (которые указывают на первый байт, 01)

[01] [02] [03] [04] [05] [ 06] [07] [08] [09] [10] [11] [12]
[ВТР VTableA] [ВТР VTableB] [ВТР VTableC]

В C++, только 1 реализация будет сгенерирован для прототипа функции в сценарии с несколькими интерфейсами. Однако для обычного сценария наследования суперкласс может иметь предопределенную реализацию, а дети, которые переопределяют функцию, будут иметь свои VTables, указывающие на другой контент, чем родительский.

 Смежные вопросы

  • Нет связанных вопросов^_^