// IVehicle methods
// методы IVehicle
STDMETHODIMP GetMaxSpeed(long *pMax);
// ICar methods
// методы ICar
STDMETHODIMP Brake(void);
// IPlane methods
// методы IPlane
STDMETHODIMP TakeOff(void);
// standard heap-based QI/AddRef/Release
// стандартные расположенные в «куче» QI/AddRef/Release
IMPLEMENT_UNKNOWN(CarBoatPlane)
BEGIN_INTERFACE_TABLE(CarBoatPlane)
IMPLEMENTS_INTERFACE_AS(IVehicle, ICar)
IMPLEMENTS_INTERFACE(ICar)
IMPLEMENTS_INTERFACE(IPlane)
// macro that calculates offset of data member
// макрос, вычисляющий смещение элемента данных
IMPLEMENTS_INTERFACE_WITH_COMPOSITE(IBoat, XBoat, m_xBoat)
END_INTERFACE_TABLE() };
В приведенном выше определении класса опущены только определения методов объекта вне
// inttable.h
// (book-specific header file)
// (заголовочный файл, специфический для данной книги)
#define COMPOSITE_OFFSET(ClassName, BaseName,
MemberType, MemberName)
(DWORD(static_cast<BaseName*>(
reinterpret_cast<MemberType*>(0x10000000 +
offsetof(ClassName, MemberName)))) – 0х10000000)
#define IMPLEMENTS_INTERFACE_WITH_COMPOSITE(Req,
MemberType, MemberName)
{ &IID_##Req,ENTRY_IS_OFFSET, COMPOSITE_OFFSET(_IT,
Req, MemberType, MemberName) },
// impunk.h
// (book-specific header file)
// (заголовочный файл, специфический для данной книги)
#define IMPLEMENT_COMPOSITE_UNKNOWN(OuterClassName,
InnerClassName, DataMemberName)
OuterClassName *This()
{ return (OuterClassName*)((char*)this –
offsetof(OuterClassName, DataMemberName)); }
STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
{ return This()->QueryInterface(riid, ppv); }
STDMETHODIMP_(ULONG) AddRef(void)
{ return This()->AddRef(); }
STDMETHODIMP_(ULONG) Release(void)
{ return This()->Release(); }
Эти макросы препроцессора просто дублируют фактические реализации
Динамическая композиция
Если для реализации интерфейса в классе C++ используется множественное наследование или композиция, то в каждом объекте этого класса будут содержаться служебные данные (
Вспомним правило, гласящее, что все запросы
Реализация
1) главный объект динамически размещает отделяемый интерфейс вместо того, чтобы иметь элемент данных экземпляра, и
2) отделяемый композит должен содержать явный обратный указатель на главный объект, так как технология фиксированного смещения, используемая в композиции, здесь не работает, поскольку отделяемый интерфейс изолирован от основного объекта. Следующий класс реализует