Сущность технологии COM




Двоичная композиция - часть 6


Это и есть реализация по умолчанию, на которую ссылаются таблицы vtbl всех объектов, и это именно та версия, которую видят внешние клиенты. Объект должен также иметь неделегирующую реализацию IUnknown, которая выставляется только агрегирующему внешнему объекту.

Имеется несколько возможностей обеспечить две различные реализации IUnknown от одного объекта. Самый прямой путь — это использование композиции и элемента данных для реализации неделегирующих методов IUnknown. Ниже показана реализация Car, поддающаяся агрегации:

class Car : public ICar { LONG m_cRef; IUnknown *m_pUnk0uter; public: Car(IUnknown *pUnk0uter); // non-delegating IUnknown methods // неделегирующие методы IUnknown STDMETHODIMP InternalQueryInterface(REFIID, void **); STDMETHODIMP (ULONG) InternalAddRef(void); STDMETHODIMP_(ULONG) InternalRelease(void); // delegating IUnknown methods // делегирующие методы IUnknown STDMETHODIMP QueryInterface(REFIID, void **); STDMETHODIMP_(ULONG) AddRef(void); STDMETHODIMP_(ULONG) Release(void); STDMETHODIMP GetMaxSpeed(*long *pn); STDMETHODIMP Brake(void); // composite to map distinguished IUnknown vptr to // non-delegating InternalXXX routines 1n main object // композит для преобразования определенного vptr IUnknown // в неделегирующие подпрограммы InternalXXX в главном // объекте

class XNDUnknown : public IUnknown { Car* This() { return (Car*)((BYTE*)this - offsetof(Car, m_innerUnknown));} STDMETHODIMP QueryInterface(REFIID r, void**p) { return This()->InternalQueryInterface(r,p); } STDMETHODIMP_(ULONG) AddRef(void) { return This()->InternalAddRef(); } STDMETHODIMP_(ULONG) Release(void) { return This()->InternalRelease(); } };

XNDUnknown m_innerUnknown; // composite instance // экземпляр композита };

Двоичное размещение этого объекта показано на рис. 4.8. Методы делегирования класса чрезвычайно просты:

STDMETHODIMP Car::QueryInterface(REFIID riid, void **ppv) { return m_pUnkOuter->QueryInterface(riid, ppv); }

STDMETHODIMP_(ULONG) Car::AddRef(void) { return m_pUnkOuter->AddRef(); }




Содержание  Назад  Вперед