, , IUnknown. Dog/Cat. ++- , IPug ICat, :
class PugCat : public IPug, public ICat
C++ . PugCat , PugCat vptr, vtbl, IPug. PugCat vptr, vtbl, ICat. 2.5 , .
- - , , . , ( , QueryInterface, AddRef . .) , vtbl , . C++.
, , IPug ICat:
class PugCat : public IPug, public ICat { LONG m_cRef; protected: virtual ~PugCat(void); public: PugCat(void); // IUnknown methods // IUnknown STDMETHODIMP QueryInterface(REFIID riid, void **ppv); STDMETHODIMP_(ULONG) AddRef(void); STDMETHODIMP_(ULONG) Release(void); // IAnimal methods // IAnimal STDMETHODIMP Eat(void); // IDog methods // IDog STDMETHODIMP Bark(void); // IPug methods // IPug STDMETHODIMP Snore(void); // ICat methods // ICat STDMETHODIMP IgnoreMaster(void); };
, , , , , , (implied) ( , IDog, IAnimal). , , STDMETHODIMP STDMETHODIMP_. Win32, Microsoft C++, SDK :
#define STDMETHODIMP HRESULT _stdcall #define STDMETHODIMP_(type) type _stdcall
SDK STDMETHOD STDMETHOD_, IDL- . .
AddRef Release . m_cRef , . :
PugCat::PugCat(void) : m_cRef(0) // initialize reference count to zero // { }
AddRef , . :
STDMETHODIMP_(ULONG) AddRef(void) { return ++m_cRef; }
Release , , . , , delete :
STDMETHODIMP_(ULONG) Release(void) { LONG res = --m_cRef; if (res == 0) delete this; return res; }
, , .
, Addref Release ( ). , , ( , 5). , , Win32 InterlockedIncrement/InterlockedDecrement:
STDMETHODIMP_(ULONG) AddRef(void) { return InterlockedIncrement(&m_cRef); } STDMETHODIMP_(ULONG) Release(void) { LONG res = InterlockedDecrement(&m_cRef); if (res == 0) delete this; return res; }
, , C++. , , InterlockedIncrement / InterlockedDecrement, , .
AddRef Release , ( " ") ++- new. , . , . delete Release . , , delete this, , :
STDMETHODIMP_(ULONG) GlobalVar::AddRef(void) { return 2; // any non-zero value is legal // } STDMETHODIMP_(ULONG) GlobalVar::Release (void) { return 1; // any non-zero value is legal // }
, AddRef Release .
AddRef Release IUnknown QueryInterface. . PugCat, , QueryInterface:
STDMETHODIMP PugCat::QueryInterface(REFIID riid, void **ppv) { assert(ppv != 0); // or return E_POINTER in production // E_POINTER if (riid == IID_IPug) *ppv = static_cast<IPug*>(this); else if (riid == IID_IDog) *ppv = static_cast<IDog*>(this); else if (riid == IID_IAnimal) // cat or pug? // ? *ppv == static_cast<IDog*>(this); else if (riid == IID_IUnknown) // cat or pug? // ? *ppv = static_cast<IDog*>(this); else if (riid == IID_ICat) *ppv = static_cast<ICat*>(this); else { // unsupported interface // *ppv = 0; return E_NOINTERFACE; } // if we reach this point, *ppv is non-null // and must be AddRef'ed (guideline A2) // , *ppv // AddRef' ( A2) reinterpret_cast<IUnknown*>(*ppv)->AddRef(); return S_OK; }
static_cast , :
*ppv = (IPug*)this;
static_cast , .
, QueryInterface , ( , IUnknown, IAnimal) . , PugCat :
if (riid == IID_IUnknown) *ppv = static_cast<IUnknown*>(this);
, . FastString IExtensibleObject . :
if (riid == IID_IUnknown) ppv = static_cast<IDog*>(this);
if (riid == IID_IUnknown) ppv = static_cast<ICat*>(this);
PugCat. , , 1.
1 vtbl , (adjuster thunk) this . , . Microsoft C++ .