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**, Π±Π΅Π· ΠΊΠ°ΠΊΠΈΡ -Π»ΠΈΠ±ΠΎ Π·Π°ΡΡΠ°Ρ Π½Π° ΡΡΠ°ΠΏΠ΅ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ.
Π Π΅Π°Π»ΠΈΠ·Π°ΡΠΈΡ IUnknown
ΠΠΌΠ΅Ρ ΠΎΠΏΠΈΡΠ°Π½Π½ΡΠ΅ Π²ΡΡΠ΅ ΠΎΠ±ΡΠ°Π·ΡΡ ΠΊΠ»ΠΈΠ΅Π½ΡΡΠΊΠΎΠ³ΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ, Π»Π΅Π³ΠΊΠΎ Π²ΠΈΠ΄Π΅ΡΡ, ΠΊΠ°ΠΊ ΡΠ΅Π°Π»ΠΈΠ·ΠΎΠ²Π°ΡΡ ΠΌΠ΅ΡΠΎΠ΄Ρ 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 mcRef;
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