, . 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, :
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 .