÷ DuplicatePointer DestroyPointer , AddRef Release IUnknown ÷ , , . , . AddRef/Release , , .
(Component Object Model Specification) ÷ ÷ . ø ÷ - C++. ÷ :
, ÷ (, ÷ ). , ÷ AddRef Release , . ÷ ÷, ø ÷, 8500 ÷ 14.4 /, ÷ ÷ .
ø ÷ , , ÷ , AddRef Release . ÷ , AddRef :
÷ , Release :
÷ , , ÷ [in] :
, , .
× ÷ , , ÷ , :
{% if main.adsdop %}{% include 'adsenceinline.tpl' %}{% endif %}void GetObject([out] IUnknown **ppUnk);
÷ , :
void UseObject([in] IUnknown *pUnk);
, ÷ . , , :
void GetAndUse(/* [out] */ IUnknown ** ppUnkOut)
{
IUnknown *pUnk1 = 0, *pUnk2 = 0;
*ppUnkOut =0; // R3
// get pointers to one (or two) objects
// получаем указатели на один (или два) объекта
GetObject(&pUnk1); //A2
GetObject(&pUnk2); //A1
// set pUnk2 to point to first object
// устанавливаем pUnk2, чтобы указать на первый объект
if (pUnk2) pUnk2->Release(): //R1
if (pUnk2 = pUnk1) pUnk2->AddRef(): //A1
// pass pUnk2 to some other function
// передаем pUnk2 какой-нибудь другой функции
UseObject(pUnk2); //S1
// return pUnk2 to caller using ppUnkOut parameter
// возвращаем pUnk2 вызывающему объекту, используя
// параметр ppUnkOut
if (*ppUnkOut = pUnk2) (*ppUnkOut)->AddRef(); // A2
// falling out of scope so clean up
// выходит за область действия и поэтому освобождаем
if (pUnk1) pUnkl->Release(); //R2
if (pUnk2) pUnk2->Release(); //R2
}
, ÷ ø A2 , ÷. GetObject , GetObject . ÷, ÷ GetObject AddRef ÷ [out] . , ppUnkOut , AddRef ÷ .
AddRef Release , . AddRef , Release ÷ 32- ÷ . ÷ ÷ ø AddRef Release . ÷, ÷ , , , ÷ ÷ ÷ ÷ , , .
÷, , Release . Release , ÷ . . ÷, ÷ Release , , ÷ . ÷, Release , AddRef , ÷ . , ÷ - ÷, , , , . × (released) , , , Release :
inline void SafeRelease(IUnknown * &rpUnk)
{
if (rpUnk) {
rpUnk->Release();
rpUnk = 0;
// rpUnk passed by reference
// rpUnk, переданный ссылкой
}
}
, ø . ø , , .
, AddRef Release , . GetAndUse , , ÷ . ÷, ÷ , , ø . ø , - return , ÷ , (unhandled) ÷ C++, - ø , , ÷ . ÷, ÷ , , ÷ C++. ÷, , , ÷ . -, ÷ Release .
, ÷ ÷ . ß C++ ÷ dynamic_cast . , - , ÷ dynamic_cast . IDL- QueryInterface :
HRESULT QueryInterface([in] REFIID riid, [out] void **ppv);
( riid ) ÷ ø . (ppv) , ÷ ø ø ø .
QueryInterface , ø , E_NOINTERFACE *ppv ÷. ø , *ppv ø HRESULT S_OK . ppv [out] -, QueryInterface AddRef , (. ø 2). AddRef Release . ÷ C++ dynamic_cast Dog/Cat , :
void TryToSnoreAndIgnore(/* [in] */ IUnknown *pUnk)
{
IPug *pPug = 0;
pPug = dynamic_cast<IPug*> (pUnk);
if (pPug)
// the object is Pug-compatible
// объект совместим с Pug
pPug->Snore();
ICat *pCat = 0;
pCat = dynamic_cast<ICat*>(pUnk);
if (pCat)
// the object is Cat-compatible
// объект совместим с Cat pCat->
IgnoreMaster();
}
, , ICat IDog , . ICat IDog , ( ). ÷ QueryInterface :
void TryToSnoreAndIgnore(/* [in] */ IUnknown *pUnk)
{
HRESULT hr;
IPug *pPug = 0;
hr = pUnk->QueryInterface(IID_IPug, (void**)&pPug);
if (SUCCEEDED(hr)) {
// the object is Pug-compatible
// объект совместим с Pug
pPug->Snore();
pPug->Release(); // R2
}
ICat *pCat = 0;
hr = pUnk->QueryInterface(IID_ICat, (void**)&pCat);
if (SUCCEEDED(hr)) {
// the object is Cat-compatible
// объект совместим с Cat
pCat->IgnoreMaster();
pCat->Release(); // R2
}
}
÷ ÷ , , ÷ , QueryInterface , ÷ ÷ .
, QueryInterface . QueryInterface -, . 4 . , , ÷, ÷ AddRef Release . . ÷, ÷ ø÷:
void BadCOMCode(/*[in]*/ IUnknown *pUnk)
{
ICat *pCat = 0;
IPug *pPug = 0;
HRESULT hr;
hr = pUnk->QueryInterface(IID_ICat, (void**)&pCat);
if (FAILED(hr)) goto cleanup;
hr = pUnk->QueryInterface(IID_IPug, (void**)&pPug);
if (FAILED(hr)) goto cleanup;
pPug->Bark();
pCat->IgnoreMaster();
cleanup:
if (pCat) pUnk->Release();
// pCat got AddRefed in QI
// pCat получил AddRef в QI
if (pPug) pUnk->Release();
// pDog got AddRefed in QI
// pDog получил AddRef в QI
}
÷ : pCat , pPug pUnk - , AddRef , pCat pPug QueryInterface , Release pUnk . :
cleanup:
if (pCat) pCat->Release();
// use AddRefed ptr
// используем указатель AddRef
if (pPug) pPug->Release();
// use AddRefed ptr
// используем указатель AddRef
Release , AddRef (÷ ø , QueryInterface ). ÷ ÷ . , ø ÷ , ÷ , ÷ .
QueryInterface , void** . , ÷ QueryInterface , , C++:
HRESULT _stdcall QueryInterface(REFIID riid, void** ppv);
÷ , QueryInterface , ÷ IID , :
{% if main.adsdop %}{% include 'adsenceinline.tpl' %}{% endif %}IPug *pPug = 0; hr = punk->QueryInterface(IID_IPug, (void**)&pPug);
, C++ :
IPug *pPug = 0; hr = punk->QueryInterface(IID_ICat, (void**)&pPug);
ø:
IPug *pPug = 0; hr = punk->QueryInterface(IID_IPug, (void**)pPug);
, ÷ , QueryInterface e ÷ :
HRESULT QueryInterface(REFIID riid, IUnknown** ppv);
( upcasting ) , :
IDerived **ppd; IBase **ppb = ppd; // illegal // неверно
To ÷ . :
HRESULT QueryInterface(const IID& riid, void* ppv);
(cast). , ø ø ÷ ø ( ø ø ), , ÷ , ÷ ÷ C++ . QueryInterface , , Microsoft, , , . ø ø, c QueryInterface , - , ÷ IID , QueryInterface . QueryInterface "" . :
#define IID_PPV_ARG(Type, Expr) IID_##type, \ reinterpret_cast<void**>(static_cast<Type **>(Expr))
1 , ÷ , QueryInterface , ÷ (indirecton):
IPug *pPug = 0; hr = punk->QueryInterface(IID_PPV_ARG(IPug, &pPug));
ø, void** , - .
1 ÷ Tye McQueen .