Π§ΠΈΡ‚Π°ΠΉΡ‚Π΅ ΠΊΠ½ΠΈΠ³ΠΈ ΠΎΠ½Π»Π°ΠΉΠ½ Π½Π° Bookidrom.ru! БСсплатныС ΠΊΠ½ΠΈΠ³ΠΈ Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΊΠ»ΠΈΠΊΠ΅

Π§ΠΈΡ‚Π°Ρ‚ΡŒ ΠΎΠ½Π»Π°ΠΉΠ½ Β«Π‘ΡƒΡ‰Π½ΠΎΡΡ‚ΡŒ Ρ‚Π΅Ρ…Π½ΠΎΠ»ΠΎΠ³ΠΈΠΈ БОМ. Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° программиста». Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Π° 41

Автор Π”ΠΎΠ½Π°Π»ΡŒΠ΄ Бокс

// (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(); }


Π­Ρ‚ΠΈ макросы прСпроцСссора просто Π΄ΡƒΠ±Π»ΠΈΡ€ΡƒΡŽΡ‚ фактичСскиС Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ QueryInterface, AddRef ΠΈ Release , ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Π½Π½Ρ‹Π΅ Π² ΠΊΠΎΠΌΠΏΠΎΠ·ΠΈΡ†ΠΈΠΈ.


ДинамичСская композиция

Если для Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ интСрфСйса Π² классС C++ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ мноТСствСнноС наслСдованиС ΠΈΠ»ΠΈ композиция, Ρ‚ΠΎ Π² ΠΊΠ°ΠΆΠ΄ΠΎΠΌ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π΅ этого класса Π±ΡƒΠ΄ΡƒΡ‚ ΡΠΎΠ΄Π΅Ρ€ΠΆΠ°Ρ‚ΡŒΡΡ слуТСбныС Π΄Π°Π½Π½Ρ‹Π΅ (overhead) указатСля vptr Ρ€Π°Π·ΠΌΠ΅Ρ€ΠΎΠΌ Π² Ρ‡Π΅Ρ‚Ρ‹Ρ€Π΅ Π±Π°ΠΉΡ‚Π° Π½Π° ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅ΠΌΡ‹ΠΉ интСрфСйс (принимая, Ρ‡Ρ‚ΠΎ sizeof (void*) == 4). Если число интСрфСйсов, экспортируСмых ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠΌ, Π½Π΅Π²Π΅Π»ΠΈΠΊΠΎ, Ρ‚ΠΎ эти слуТСбныС Π΄Π°Π½Π½Ρ‹Π΅ Π½Π΅ ΠΈΠ³Ρ€Π°ΡŽΡ‚ Π²Π°ΠΆΠ½ΠΎΠΉ Ρ€ΠΎΠ»ΠΈ, особСнно Π² свСтС прСимущСств, прСдоставляСмых ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½ΠΎΠΉ модСлью БОМ. Если, ΠΎΠ΄Π½Π°ΠΊΠΎ, число ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅ΠΌΡ‹Ρ… интСрфСйсов Π²Π΅Π»ΠΈΠΊΠΎ, Ρ‚ΠΎ Ρ€Π°Π·ΠΌΠ΅Ρ€ слуТСбных Π΄Π°Π½Π½Ρ‹Ρ… vptr ΠΌΠΎΠΆΠ΅Ρ‚ вырасти Π΄ΠΎ Ρ‚Π°ΠΊΠΎΠΉ стСпСни, Ρ‡Ρ‚ΠΎ Ρ‡Π°ΡΡ‚ΡŒ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°, Π½Π΅ связанная с БОМ, Π±ΡƒΠ΄Π΅Ρ‚ ΠΊΠ°Π·Π°Ρ‚ΡŒΡΡ малСнькой ΠΏΠΎ ΡΡ€Π°Π²Π½Π΅Π½ΠΈΡŽ с Π½ΠΈΠΌΠΈ. ΠŸΡ€ΠΈ использовании ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ ΠΈΠ· этих интСрфСйсов всС врСмя Π±Π΅Π· слуТСбных Π΄Π°Π½Π½Ρ‹Ρ… Π½Π΅ ΠΎΠ±ΠΎΠΉΡ‚ΠΈΡΡŒ. Если ΠΆΠ΅, ΠΎΠ΄Π½Π°ΠΊΠΎ, эти интСрфСйсы Π½Π΅ Π±ΡƒΠ΄ΡƒΡ‚ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ Π½ΠΈΠΊΠΎΠ³Π΄Π° ΠΈΠ»ΠΈ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ Π² Ρ‚Π΅Ρ‡Π΅Π½ΠΈΠ΅ ΠΊΠΎΡ€ΠΎΡ‚ΠΊΠΎΠ³ΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ, Ρ‚ΠΎ ΠΌΠΎΠΆΠ½ΠΎ Π²ΠΎΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ Π»Π°Π·Π΅ΠΉΠΊΠΎΠΉ Π² Π‘ΠΏΠ΅Ρ†ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΠΈ БОМ ΠΈ ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ vptr Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… Π½Π΅ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹Ρ… ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ².

Вспомним ΠΏΡ€Π°Π²ΠΈΠ»ΠΎ, гласящСС, Ρ‡Ρ‚ΠΎ всС запросы QueryInterface Π½Π° ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ ΠΎΡ‚Π½ΠΎΡΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ IUnknown Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Ρ‚ΡŒ Ρ‚ΠΎΡ‡Π½ΠΎ Ρ‚Π°ΠΊΠΎΠ΅ ΠΆΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ указатСля. ИмСнно Ρ‚Π°ΠΊ Π² БОМ обСспСчиваСтся идСнтификация ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ². Π’ Ρ‚ΠΎ ΠΆΠ΅ врСмя БпСцификация БОМ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½ΠΎ Ρ€Π°Π·Ρ€Π΅ΡˆΠ°Π΅Ρ‚ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Ρ‚ΡŒ Π΄Ρ€ΡƒΠ³ΠΈΠ΅ значСния ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»Π΅ΠΉ Π² ΠΎΡ‚Π²Π΅Ρ‚ Π½Π° запросы QueryInterface ΠΎΡ‚Π½ΠΎΡΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ Π»ΡŽΠ±Ρ‹Ρ… Π΄Ρ€ΡƒΠ³ΠΈΡ… Ρ‚ΠΈΠΏΠΎΠ² интСрфСйсов, ΠΊΡ€ΠΎΠΌΠ΅ IUnknown. Π­Ρ‚ΠΎ ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ для нСчасто ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹Ρ… интСрфСйсов ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ ΠΌΠΎΠΆΠ΅Ρ‚ динамичСски Π²Ρ‹Π΄Π΅Π»ΡΡ‚ΡŒ ΠΏΠ°ΠΌΡΡ‚ΡŒ для vptr ΠΏΠΎ Ρ‚Ρ€Π΅Π±ΠΎΠ²Π°Π½ΠΈΡŽ, Π½Π΅ Π·Π°Π±ΠΎΡ‚ΡΡΡŒ ΠΎ Π²ΠΎΠ·Π²Ρ€Π°Ρ‚Π΅ Ρ‚ΠΎΠ³ΠΎ ΠΆΠ΅ самого динамичСски Π²Ρ‹Π΄Π΅Π»Π΅Π½Π½ΠΎΠ³ΠΎ Π±Π»ΠΎΠΊΠ° памяти ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ Ρ€Π°Π·, ΠΊΠΎΠ³Π΄Π° Π·Π°ΠΏΡ€Π°ΡˆΠΈΠ²Π°Π΅Ρ‚ΡΡ ΠΊΠ°ΠΊΠΎΠΉ-Π»ΠΈΠ±ΠΎ интСрфСйс. Π­Ρ‚Π° тСхнология Π²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠ³ΠΎ (transient) размСщСния ΠΊΠΎΠΌΠΏΠΎΠ·ΠΈΡ‚ΠΎΠ² Π²ΠΏΠ΅Ρ€Π²Ρ‹Π΅ Π±Ρ‹Π»Π° описана Π² Β«Π±Π΅Π»ΠΎΠΉ ΠΊΠ½ΠΈΠ³Π΅Β» Microsoft ΠŸΠΎΠ²Π°Ρ€Π΅Π½Π½Π°Ρ ΠΊΠ½ΠΈΠ³Π° для программистов БОМ (Microsoft white paper The БОМ Programmer's Cookbook), написанной ΠšΡ€ΠΈΡΠΏΠΈΠ½ΠΎΠΌ ГосвСллом (Crispin Goswell) (http://www.microsoft.com/oledev). Π’ этой Β«Π±Π΅Π»ΠΎΠΉ ΠΊΠ½ΠΈΠ³Π΅Β» Ρ‚Π°ΠΊΠΈΠ΅ Π²Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ интСрфСйсы Π½Π°Π·Ρ‹Π²Π°ΡŽΡ‚ΡΡ отдСляСмыми (tearoff).

РСализация отдСляСмого интСрфСйса ΠΏΠΎΠ΄ΠΎΠ±Π½Π° Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ интСрфСйса с использованиСм ΠΊΠΎΠΌΠΏΠΎΠ·ΠΈΡ†ΠΈΠΈ. Для отдСляСмого интСрфСйса Π΄ΠΎΠ»ΠΆΠ΅Π½ Π±Ρ‹Ρ‚ΡŒ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ Π²Ρ‚ΠΎΡ€ΠΎΠΉ класс, Π½Π°ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ Ρ‚ΠΎΠΌΡƒ интСрфСйсу, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΎΠ½ Π±ΡƒΠ΄Π΅Ρ‚ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Ρ‹Π²Π°Ρ‚ΡŒ. Π§Ρ‚ΠΎΠ±Ρ‹ ΠΎΠ±Π΅ΡΠΏΠ΅Ρ‡ΠΈΡ‚ΡŒ ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΡŽ, QueryInterface отдСляСмого интСрфСйса Π΄ΠΎΠ»ΠΆΠ΅Π½ Π΄Π΅Π»Π΅Π³ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ QueryInterface основного класса. Π”Π²Π° основных различия Π·Π°ΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‚ΡΡ Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ:

1) Π³Π»Π°Π²Π½Ρ‹ΠΉ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ динамичСски Ρ€Π°Π·ΠΌΠ΅Ρ‰Π°Π΅Ρ‚ отдСляСмый интСрфСйс вмСсто Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΈΠΌΠ΅Ρ‚ΡŒ элСмСнт Π΄Π°Π½Π½Ρ‹Ρ… экзСмпляра, ΠΈ

2) отдСляСмый ΠΊΠΎΠΌΠΏΠΎΠ·ΠΈΡ‚ Π΄ΠΎΠ»ΠΆΠ΅Π½ ΡΠΎΠ΄Π΅Ρ€ΠΆΠ°Ρ‚ΡŒ явный ΠΎΠ±Ρ€Π°Ρ‚Π½Ρ‹ΠΉ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ Π½Π° Π³Π»Π°Π²Π½Ρ‹ΠΉ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ тСхнология фиксированного смСщСния, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΠ°Ρ Π² ΠΊΠΎΠΌΠΏΠΎΠ·ΠΈΡ†ΠΈΠΈ, здСсь Π½Π΅ Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ отдСляСмый интСрфСйс ΠΈΠ·ΠΎΠ»ΠΈΡ€ΠΎΠ²Π°Π½ ΠΎΡ‚ основного ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°. Π‘Π»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ класс Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΠ΅Ρ‚ IBoat ΠΊΠ°ΠΊ отдСляСмый интСрфСйс:


class CarBoat : public ICar

{

LONG m_cRef;

CarBoat (void): m_cRef(0) {}

public:

// IUnknown methods

// ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ IUnknown

STDMETHODIMP QueryInterface(REFIID, void**);

STDMETHODIMP_(ULONG) AddRef(void);

STDMETHODIMP_(ULONG) Release(void);

// IVehicle methods

// ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ IVehicle

STDMETHODIMP GetMaxSpeed(long *pMax);

// ICar methods

// ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ ICar

STDMETHODIMP Brake(void);

// define nested class that implements IBoat

// опрСдСляСм Π²Π»ΠΎΠΆΠ΅Π½Π½Ρ‹ΠΉ класс, Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΡŽΡ‰ΠΈΠΉ IBoat

struct XBoat : public IBoat

{

LONG m_cBoatRef;

// back pointer to main object is explicit member

// ΠΎΠ±Ρ€Π°Ρ‚Π½Ρ‹ΠΉ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ Π½Π° Π³Π»Π°Π²Π½Ρ‹ΠΉ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ – явный Ρ‡Π»Π΅Π½

CarBoat *m_pThis;

inline CarBoat* This()

{

return m_pThis;

}

XBoat(CarBoat *pThis);

~XBoat(void);

STDMETHODIMP QueryInterface(REFIID, void**);

STDMETHODIMP_(ULONG) AddRef(void);

STDMETHODIMP_(ULONG) Release(void);

STDMETHODIMP GetMaxSpeed(long *pval);

STDMETHODIMP Sink(void);

};

// note: no data member of type Xboat

// Π·Π°ΠΌΠ΅Ρ‚ΠΈΠΌ: Π½Π΅Ρ‚ элСмСнтов Π΄Π°Π½Π½Ρ‹Ρ… Ρ‚ΠΈΠΏΠ° Xboat

};


Для QueryInterface Π³Π»Π°Π²Π½ΠΎΠ³ΠΎ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ динамичСски Ρ€Π°Π·ΠΌΠ΅ΡΡ‚ΠΈΡ‚ΡŒ Π½ΠΎΠ²Ρ‹ΠΉ отдСляСмый интСрфСйс – ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ Ρ€Π°Π·, ΠΊΠΎΠ³Π΄Π° Π·Π°ΠΏΡ€Π°ΡˆΠΈΠ²Π°Π΅Ρ‚ΡΡ IBoat:


STDMETHODIMP CarBoat::QueryInterface(REFIID riid, void **ppv)

{

if (riid == IID_IBoat)

*ppv = static_cast<IBoat*>(new XBoat(this));

else if (riid == IID_IUnknown)

*ppv = static_cast<IUnknown*>(this);

:

:


ΠšΠ°ΠΆΠ΄Ρ‹ΠΉ Ρ€Π°Π· ΠΏΡ€ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠΈ запроса Π½Π° интСрфСйс IBoat размСщаСтся Π½ΠΎΠ²Ρ‹ΠΉ отдСляСмый интСрфСйс. Богласно стандартной ΠΏΡ€Π°ΠΊΡ‚ΠΈΠΊΠ΅ QueryInterface Π²Ρ‹Π·ΠΎΠ²Π° AddRef посрСдством Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚ΠΈΡ€ΡƒΡŽΡ‰Π΅Π³ΠΎ указатСля: ((IUnknown*)*ppv)->AddRef();

AddRef Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ‚ΡŒ нСпосрСдствСнно ΠΈΠ· QueryInterface Ρ‚ΠΎΠ»ΡŒΠΊΠΎ отдСляСмый интСрфСйс. Π’Π°ΠΆΠ½ΠΎ Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ Π³Π»Π°Π²Π½Ρ‹ΠΉ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ остаСтся Π² памяти ΡΡ‚ΠΎΠ»ΡŒΠΊΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ, сколько сущСствуСт отдСляСмый интСрфСйс. ΠŸΡ€ΠΎΡΡ‚Π΅ΠΉΡˆΠΈΠΉ ΠΏΡƒΡ‚ΡŒ ΠΎΠ±Π΅ΡΠΏΠ΅Ρ‡ΠΈΡ‚ΡŒ это – Π·Π°ΡΡ‚Π°Π²ΠΈΡ‚ΡŒ сам отдСляСмый интСрфСйс ΠΏΡ€Π΅Π΄ΡΡ‚Π°Π²Π»ΡΡ‚ΡŒ Π½Π΅ΠΎΡΠ²ΠΎΠ±ΠΎΠΆΠ΄Π΅Π½Π½ΡƒΡŽ ссылку. Π­Ρ‚ΠΎ ΠΌΠΎΠΆΠ½ΠΎ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π² Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ΅ ΠΈ дСструкторС отдСляСмого интСрфСйса:


CarBoat::XBoat::XBoat(CarBoat *pThis) : m_cBoatRef(0), m_pThis(pThis)

{

m_pThis->AddRef();

}

CarBoat::XBoat::~XBoat(void)

{

m_pThis->Release();

}


Как ΠΈ Π² случаС с ΠΊΠΎΠΌΠΏΠΎΠ·ΠΈΡ†ΠΈΠ΅ΠΉ, ΠΌΠ΅Ρ‚ΠΎΠ΄Ρƒ QueryInterface отдСляСмого интСрфСйса трСбуСтся ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΡ†ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚, дСлСгируя освобоТдСниС Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π³Π»Π°Π²Π½ΠΎΠ³ΠΎ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°. Однако отдСляСмый интСрфСйс ΠΌΠΎΠΆΠ΅Ρ‚ Π²Ρ‹ΡΠ²Π»ΡΡ‚ΡŒ запросы Π½Π° Ρ‚ΠΎΡ‚ интСрфСйс (интСрфСйсы), ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΎΠ½ сам Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΠ΅Ρ‚, ΠΈ просто Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Ρ‚ΡŒ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ, ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Π°Π½Π½Ρ‹ΠΉ AddRef, сСбС самому:


STDMETHODIMP CarBoat::XBoat::QueryInterface(REFIID riid, void**ppv)

{

if (riid != IID_IBoat) return This()->QueryInterface(riid, ppv);

*ppv = static_cast<IBoat*>(this);

reinterpret_cast<IUnknown*>(*ppv)->AddRef();

return S_OK;

}


Π’Π²ΠΈΠ΄Ρƒ Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎ отдСляСмый интСрфСйс Π΄ΠΎΠ»ΠΆΠ΅Π½ ΡΠ°ΠΌΠΎΡƒΠ½ΠΈΡ‡Ρ‚ΠΎΠΆΠ°Ρ‚ΡŒΡΡ, ΠΊΠΎΠ³Π΄Π° ΠΎΠ½ большС Π½Π΅ Π½ΡƒΠΆΠ΅Π½, ΠΎΠ½ Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Ρ‚ΡŒ свой собствСнный счСтчик ссылок ΠΈ ΡƒΠ½ΠΈΡ‡Ρ‚ΠΎΠΆΠ°Ρ‚ΡŒ сСбя, ΠΊΠΎΠ³Π΄Π° этот счСтчик достигнСт нуля. Как ΠΎΡ‚ΠΌΠ΅Ρ‡Π°Π»ΠΎΡΡŒ Ρ€Π°Π½Π΅Π΅, дСструктор отдСляСмого интСрфСйса освободит Π³Π»Π°Π²Π½Ρ‹ΠΉ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ Π΄ΠΎ Ρ‚ΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ сам исчСзнСт ΠΈΠ· памяти:


STDMETHODIMP_(ULONG) CarBoat::XBoat::AddRef (void)

{

return InterlockedIncrement(&m_cRef);

}

STDMETHODIMP_(ULONG) CarBoat::XBoat::Release(void)

{

ULONG res = InterlockedDecrement(&m_cBoatRef);

if (res == 0) delete this;

// dtor releases main object

// дСструктор освобоТдаСт Π³Π»Π°Π²Π½Ρ‹ΠΉ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚

return res;

}


Как ΠΈ Π² случаС с ΠΊΠΎΠΌΠΏΠΎΠ·ΠΈΡ†ΠΈΠ΅ΠΉ, ΠΌΠ΅Ρ‚ΠΎΠ΄ This() ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π² Π»ΡŽΠ±Ρ‹Ρ… ΠΌΠ΅Ρ‚ΠΎΠ΄Π°Ρ… отдСляСмого интСрфСйса, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΌ трСбуСтся ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ статус Π³Π»Π°Π²Π½ΠΎΠ³ΠΎ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°. Π Π°Π·Π½ΠΈΡ†Π° состоит Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ отдСляСмым интСрфСйсам трСбуСтся явный ΠΎΠ±Ρ€Π°Ρ‚Π½Ρ‹ΠΉ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ, Π² Ρ‚ΠΎ врСмя ΠΊΠ°ΠΊ Π½ΠΎΡ€ΠΌΠ°Π»ΡŒΠ½Ρ‹Π΅ ΠΊΠΎΠΌΠΏΠΎΠ·ΠΈΡ‚Ρ‹ ΠΌΠΎΠ³ΡƒΡ‚ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ фиксированныС смСщСния, выдСляя ΠΏΠΎ Ρ‡Π΅Ρ‚Ρ‹Ρ€Π΅ Π±Π°ΠΉΡ‚Π° Π½Π° ΠΊΠΎΠΌΠΏΠΎΠ·ΠΈΡ‚.

На ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ взгляд, отдСляСмыС интСрфСйсы каТутся Π»ΡƒΡ‡ΡˆΠ΅ΠΉ ΠΈΠ· всСх возмоТностСй. Когда интСрфСйс Π½Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ, Ρ‚ΠΎ Π½Π° Π΅Π³ΠΎ слуТСбныС Π΄Π°Π½Π½Ρ‹Π΅ отводится Π½ΡƒΠ»ΡŒ Π±Π°ΠΉΡ‚ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°. Когда ΠΆΠ΅ интСрфСйс ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ, ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ косвСнно Ρ‚Ρ€Π°Ρ‚ΠΈΡ‚ 4 Π±Π°ΠΉΡ‚Π° Π½Π° слуТСбныС Π΄Π°Π½Π½Ρ‹Π΅ отдСляСмого интСрфСйса. ПодобноС Π²ΠΏΠ΅Ρ‡Π°Ρ‚Π»Π΅Π½ΠΈΠ΅ базируСтся Π½Π° Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… ΠΎΠ±ΠΌΠ°Π½Ρ‡ΠΈΠ²Ρ‹Ρ… прСдполоТСниях. Π’ΠΎ-ΠΏΠ΅Ρ€Π²Ρ‹Ρ…, Π·Π°Ρ‚Ρ€Π°Ρ‚Ρ‹ Π½Π° Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‰ΠΈΠΉ отдСляСмый интСрфСйс ΡΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‚ ΠΎΡ‚Π½ΡŽΠ΄ΡŒ Π½Π΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ 4 Π±Π°ΠΉΡ‚Π° памяти для Π΅Π³ΠΎ vptr. ΠžΡ‚Π΄Π΅Π»ΡΠ΅ΠΌΠΎΠΌΡƒ интСрфСйсу Ρ‚Ρ€Π΅Π±ΡƒΡŽΡ‚ΡΡ Ρ‚Π°ΠΊΠΆΠ΅ ΠΎΠ±Ρ€Π°Ρ‚Π½Ρ‹ΠΉ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ ΠΈ счСтчик ссылок[1]. Π’ΠΎ-Π²Ρ‚ΠΎΡ€Ρ‹Ρ…, нСсмотря Π½Π° Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ использования ΡΠΏΠ΅Ρ†ΠΈΠ°Π»ΡŒΠ½ΠΎΠ³ΠΎ распрСдСлитСля памяти (custom memory allocator ), отдСляСмому интСрфСйсу потрСбуСтся ΠΏΠΎ ΠΊΡ€Π°ΠΉΠ½Π΅ΠΉ ΠΌΠ΅Ρ€Π΅ 4 Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Ρ… Π±Π°ΠΉΡ‚Π° Π½Π° Π²Ρ‹Ρ€Π°Π²Π½ΠΈΠ²Π°Π½ΠΈΠ΅ ΠΈ/ΠΈΠ»ΠΈ Π·Π°ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΎΠ² динамичСски Π²Ρ‹Π΄Π΅Π»Π΅Π½Π½ΠΎΠΉ памяти, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹Ρ… Π‘-Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΎΠΉ для Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ malloc/operator new . Π­Ρ‚ΠΎ ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ Π΄Π΅ΠΉΡΡ‚Π²ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ экономит 4 Π±Π°ΠΉΡ‚Π°, ΠΊΠΎΠ³Π΄Π° интСрфСйс Π½Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ. Но ΠΊΠΎΠ³Π΄Π° интСрфСйс ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ, отдСляСмый интСрфСйс Ρ‚Ρ€Π°Ρ‚ΠΈΡ‚ ΠΊΠ°ΠΊ ΠΌΠΈΠ½ΠΈΠΌΡƒΠΌ 12 Π±Π°ΠΉΡ‚, Ссли ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π΅Π½ ΡΠΏΠ΅Ρ†ΠΈΠ°Π»ΡŒΠ½Ρ‹ΠΉ Ρ€Π°ΡΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚Π΅Π»ΡŒ памяти, ΠΈ 16 Π±Π°ΠΉΡ‚, Ссли, ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ, ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π΅Π½ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ new. Если интСрфСйс Π·Π°ΠΏΡ€Π°ΡˆΠΈΠ²Π°Π΅Ρ‚ΡΡ Ρ€Π΅Π΄ΠΊΠΎ, Ρ‚ΠΎ такая оптимизация ΠΈΠΌΠ΅Π΅Ρ‚ смысл, особСнно Ссли ΠΊΠ»ΠΈΠ΅Π½Ρ‚ освобоТдаСт этот интСрфСйс вскорС послС получСния. Если ΠΆΠ΅ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Ρ…Ρ€Π°Π½ΠΈΡ‚ отдСляСмый интСрфСйс Π² Ρ‚Π΅Ρ‡Π΅Π½ΠΈΠ΅ всСго Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ ΠΆΠΈΠ·Π½ΠΈ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°, Ρ‚ΠΎ прСимущСства отдСляСмого интСрфСйса Ρ‚Π΅Ρ€ΡΡŽΡ‚ΡΡ.

К соТалСнию, Π΄Π΅Π»ΠΎ с отдСляСмым интСрфСйсом обстоит Π΅Ρ‰Π΅ Ρ…ΡƒΠΆΠ΅. Как Π²ΠΈΠ΄Π½ΠΎ ΠΈΠ· ΠΏΠΎΠΊΠ°Π·Π°Π½Π½ΠΎΠΉ Ρ€Π°Π½Π΅Π΅ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ, Ссли ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ Π΄Π²Π° запроса QueryInterface Π½Π° Ρ‚ΠΎΡ‚ ΠΆΠ΅ самый отдСляСмый интСрфСйс, Ρ‚ΠΎ Π±ΡƒΠ΄ΡƒΡ‚ созданы Π΄Π²Π΅ ΠΊΠΎΠΏΠΈΠΈ этого отдСляСмого интСрфСйса, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ Π½Π° ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ ΠΈΠ· Π½ΠΈΡ… ΠΏΠΎΠ»Π½ΠΎΡΡ‚ΡŒΡŽ забываСтся Π³Π»Π°Π²Π½Ρ‹ΠΌ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠΌ, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΠ½ Π±Ρ‹Π» Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π΅Π½ Π²Ρ‹Π·Ρ‹Π²Π°ΡŽΡ‰Π΅ΠΌΡƒ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Ρƒ. Π­Ρ‚ΠΎ ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ Π² этом случаС отдСляСмый интСрфСйс Π·Π°Π½ΠΈΠΌΠ°Π΅Ρ‚ ΠΏΠΎ ΠΊΡ€Π°ΠΉΠ½Π΅ΠΉ ΠΌΠ΅Ρ€Π΅ ΠΎΡ‚ 24 Π΄ΠΎ 32 Π±Π°ΠΉΡ‚, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ Π² памяти находятся ΠΎΠ±Π° vptr отдСляСмого интСрфСйса, ΠΏΠΎ ΠΎΠ΄Π½ΠΎΠΌΡƒ Π½Π° ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ запрос QueryInterface. Π­Ρ‚Π° ΠΏΠ°ΠΌΡΡ‚ΡŒ Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ восстановлСна, ΠΏΠΎΠΊΠ° ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π½Π΅ освободит ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ отдСляСмый интСрфСйс. Битуация, ΠΊΠΎΠ³Π΄Π° Π΄Π²Π° запроса QueryInterface ΡƒΠ΄Π΅Ρ€ΠΆΠΈΠ²Π°ΡŽΡ‚ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ Π² Ρ‚Π΅Ρ‡Π΅Π½ΠΈΠ΅ всСго Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ ΠΆΠΈΠ·Π½ΠΈ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°, особСнно Π²Π°ΠΆΠ½Π°, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ ΠΈΠΌΠ΅Π½Π½ΠΎ это ΠΈ происходит ΠΏΡ€ΠΈ ΡƒΠ΄Π°Π»Π΅Π½Π½ΠΎΠΌ ΠΎΠ±Ρ€Π°Ρ‰Π΅Π½ΠΈΠΈ ΠΊ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Ρƒ. БОМ-слой, Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΡŽΡ‰ΠΈΠΉ ΡƒΠ΄Π°Π»Π΅Π½Π½Ρ‹Π΅ Π²Ρ‹Π·ΠΎΠ²Ρ‹, Π±ΡƒΠ΄Π΅Ρ‚ Π΄Π²Π°ΠΆΠ΄Ρ‹ Π·Π°ΠΏΡ€Π°ΡˆΠΈΠ²Π°Ρ‚ΡŒ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ (с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ QueryInterface) Π½Π° ΠΏΡ€Π΅Π΄ΠΌΠ΅Ρ‚ ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΈ Ρ‚ΠΎΠ³ΠΎ ΠΆΠ΅ интСрфСйса ΠΈ Π±ΡƒΠ΄Π΅Ρ‚ ΡƒΠ΄Π΅Ρ€ΠΆΠΈΠ²Π°Ρ‚ΡŒ ΠΎΠ±Π° Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° Π² Ρ‚Π΅Ρ‡Π΅Π½ΠΈΠ΅ всСго Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ ΠΆΠΈΠ·Π½ΠΈ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°. Π­Ρ‚ΠΎ ΠΎΠ±ΡΡ‚ΠΎΡΡ‚Π΅Π»ΡŒΡΡ‚Π²ΠΎ Π΄Π΅Π»Π°Π΅Ρ‚ отдСляСмыС интСрфСйсы особСнно рискованными для ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ², ΠΊ ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΌ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΎΡΡƒΡ‰Π΅ΡΡ‚Π²Π»ΡΡ‚ΡŒΡΡ ΡƒΠ΄Π°Π»Π΅Π½Π½Ρ‹ΠΉ доступ.