QueryInterface , IUnknown, IUnknown. QueryInterface IUnknown. " " , . , :
void AssertSameObject(IUnknown *pUnk) { IUnknown *pUnk1 = 0, *pUnk2 = 0; HRESULT hr1 = pUnk->QueryInterface(IID_IUnknown, (void **)&pUnk1); HRESULT hr2 = pUnk->QueryInterface(IID_IUnknown, (void **)&pUnk2); // QueryInterface(IUnknown) must always succeed // QueryInterface(IUnknown) assert(SUCCEEDED(hr1) && SUCCEEDED(hr2)); // two requests for IUnknown must always yield the // same pointer values // IUnknown // assert(pUnk1 == pUnk2); pUnk1->Release() ; pUnk2->Release() ; }
, .
bool IsSameObject(IUnknown *pUnk1, IUnknown *pUnk2) { assert(pUnk1 && pUnk2); bool bResult = true; if (pUnk1 != pUnk2) { HRESULT hr1, hr2; IUnknown *p1 = 0, *p2 = 0; hr1 = pUnk1->QueryInterface(IID_IUnknown, (void **)&p1); assert(SUCCEEDED(hr1)); hr2 = pUnk2->QueryInterface(IID_IUnknown, (void **)&p2); assert(SUCCEEDED(hr2)); // compare the two pointer values, as these // represent the identity of the object // , // bResult = ( 1 == 2); p1->Release(); p2->Release(); } return bResult; }
5 , , .
IUnknown, , . IUnknown:
class CarBoatPlane : public ICar, public IBoat, public IPlane { 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); // IBoat methods - IBoat STDMETHODIMP Sink(void); // IPlahe methods - IPlane STDMETHODIMP TakeOff(void); };
QueryInterface CarBoatPlane:
STDMETHODIMP QueryInterface(REFIID riid, void **ppv) { if (riid == IID_IUnknown) *ppv = static_cast<ICar*>(this); else if (riid == IID_IVehicle) *ppv = static_cast<ICar*>(this); else if (riid == IID_ICar) *ppv = static_cast<ICar*>(this); else if (riid == IID_IBoat) *ppv = static_cast<IBoat*>(this); else if (riid == IID_IPlane) *ppv = static_cast<IPlane*>(this); else return (*ppv = 0), E_NOINTERFACE; ((IUnknown*)*ppv)->AddRef(); return S_OK; }
, CarBoatPlane QueryInterface IUnknown, .
CarBoatPlane ICar, IPlane, IBoat, IVehicle IUnknown. vtbl CarBoatPlane QueryInterface, . QueryInterface, , A B, :
If QI(A)->B Then QI(QI(A)->B)->A
, QueryInterface, , , :
If QI(QI(A)->B)->C Then QI(A)->C
, QueryInterface , , :
QI(A)->A
QueryInterface , , .
, IUnknown:
if (riid == IID_IUnknown) *ppv = static_cast<ICar*>(this);
QueryInterface vptr :
if (riid == IID_IUnknown) { int n = rand() % 3; if (n == 0) *ppv = static_cast<ICar*>(this); else if (n == 1) *ppv = static_cast<IBoat*>(this); else if (n == 2) *ppv = static_cast<IPlane*>(this); }
++- ( IUnknown). , , , QueryInterface .