, C++. , C++, , QueryInterface. . , , , DLL, . , , ( 1). , .
, , ICar:
 class Car : public ICar {      LONG m_cRef;     Car(void) : m_cRef(0) {}     STDMETHODIMP QueryInterface(REFIID, void **);     STDMETHODIMP_(ULONG) AddRef(void);     STDMETHODIMP_(ULONG) Release(void);     STDMETHODIMP GetMaxSpeed(long *pn);     STDMETHODIMP Brake(void); }; STDMETHODIMP Car::QueryInterface(REFIID riid, void **ppv)  {     if (riid == IID_IUnknown)         *ppv = static_cast<IUnknown*>(this);     else if (riid == IID_IVehicle)         *ppv = static_cast<IVehicle*>(this);     else if (riid == IID_ICar)         *ppv = static_cast<ICar*>(this);     else         return (*ppv = 0), E_NOINTERFACE;     ((IUnknown*)*ppv)->AddRef();     return S_OK; } // car class object's IClassFactory::CreateInstance //   IClassFactory::CreateInstance //     car STDMETHODIMP CarClass::CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppv) {     Car *pCar = new Car;     if (*pCar)          return (*ppv = 0), E_OUTOFMEMORY;     pCar->AddRef();     HRESULT hr = pCar->QueryInterface(riid, ppv);     pCar->Release();     return hr; }  QueryInterface, AddRef Release.
C++, Car :
 class CarBoat : public IBoat {     LONG m_cRef;     Unknown *m_pUnkCar;     CarBoat(void);     virtual ~CarBoat(void);     STDMETHODIMP QueryInterface(REFIID, void **);     STDMETHODIMP_(ULONG) AddRef(void);     STDMETHODIMP_(ULONG) Release(void);     STDMETHODIMP GetMaxSpeed(long *pn);     STDMETHODIMP Sink(void); };  Car, :
 CarBoat::CarBoat (void) : m_cRef(0)  {     HRESULT hr = CoCreateInstance(CLSID_Car, 0, CLSCTX_ALL,                                    IID_IUnknown, (void**)&m_pUnkCar);     assert(SUCCEEDED(hr)); } CarBoat::~CarBoat(void)  {     if (m_pUnkCar)          m_pUnkCar->Release(); }  QueryInterface:
 STDMETHODIMP CarBoat::QueryInterface(REFIID riid, void **ppv)  {     if (riid == IID_IUnknown)         *ppv = static_cast<IUnknown*>(this);     else if (riid == IID_IVehicle)         *ppv = static_cast<IVehicle*>(this);     else if (riid == IID_IBoat)         *ppv = static_cast<IBoat*>(this);     else if (riid == IID_ICar)       // forward request...       //    ...         return m_pUnkCar->QueryInterface(riid, ppv);     else         return (*ppv = 0), E_NOINTERFACE;     ((IUnknown*)*ppv)->AddRef();     return S_OK; }  Car , (identity) , QueryInterface IBoat. ,
QI(IBoat)->ICar
,
QI(QI(IBoat)->ICar)->IBoat
, QueryInterface . QueryInterface IUnknown ICar IBoat , , . IUnknown , CarBoat .
. , , . QueryInterface - . - , ( ) ( ). - IUnknown, (identity) .
. . - . :
 class Handlebar : public IHandlebar { ... }; class Wheel : public IWheel {}; class Bicycle : public IBicycle {      IHandlebar * m_pHandlebar;     IWheel *m_pFrontWheel;     IWheel *m_pBackWheel; }  icycle IHandlebar ( ) IWheel ( ) QueryInterface. QueryInterface " " (is-a), (bicycle) (wheel) (handlebar). Bicycle , IBicycle :
 [object, uuid(753A8A60-A7FF-11d0-8C30-0080C73925BA)] interface IBicycle : IVehicle {     HRESULT GetHandlebar([out,retval] IHandlebar **pph);     HRESULT GetWheels([out] IWheel **ppwFront, [out] IWheel **ppwBack); }  Bicycle :
 STDMETHODIMP Bicycle::GetHandlebar(IHandlebar **pph) {     if (*pph = m_pHandlebar)         (*pph)->AddRef();     return S_OK; } STDMETHODIMP Bicycle::GetWheels(IWheel **ppwFront, IWheel **ppwBack) {     if (*ppwFront = m_pFrontWheel)          (*ppwFront)->AddRef();     if (*ppwBack = m_pBackWheel)          (*ppwBack)->AddRef();     return S_OK; }  - . , QueryInterface, .
, , , . , - , ( ) , . , (creation function), , : IUnknown , QueryInterface, AddRef Release. CreateInstance IClassFactory:
HRESULT CreateInstance([in] Unknown *pUnkOuter, [in] REFIID riid, [out, iid_is(riid)] void **ppv);
( API- CoCreateInstanceEx CoCreateInstance) (stand-alone) . CreateInstance (pUnkOuter), . , , pUnkOuter. QueryInterface, AddRef Release pUnkOuter. .
, , CarBoat :
 CarBoat::CarBoat(void) : m_cRef(0) {       // need to pass identity of self to Create routine       // to notify car object it 1s an aggregate       //                // Create       car,     -      HRESULT hr = CoCreateInstance(CLSID_Car, this,                          CLSCTX_ALL, IID_IUnknown, (void**)&m_pUnkCar);     assert(SUCCEEDED(hr)); }  CarBoat QueryInterface ICar :
 STDMETHODIMP CarBoat::QueryInterface(REFIID riid, void **ppv) {      if (riid == IID_IUnknown)          *ppv = static_cast<IUnknown*>(this);     else if (riid == IID_ICar)         // forward request...         //    ...         return m_pUnkCar->QueryInterface(riid, ppv);     else if (riid == IID_IBoat)     :    :    :  , QueryInterface , .
CreateInstance Car , IUnknown. IUnknown , : 1) , ; 2) . QueryInterface , , .
, , , IUnknown . , , - , IUnknown. , , QueryInterface, AddRef Release . , vtbl , , . IUnknown, .
IUnknown . 1 IUnknown. Car, :
 class Car : public ICar {     LONG m_cRef;     IUnknown *m_pUnk0uter;   public:     Car(IUnknown *pUnk0uter);       // non-delegating IUnknown methods        //     IUnknown      STDMETHODIMP InternalQueryInterface(REFIID, void **);     STDMETHODIMP (ULONG) InternalAddRef(void);     STDMETHODIMP_(ULONG) InternalRelease(void);       // delegating IUnknown methods       //     IUnknown     STDMETHODIMP QueryInterface(REFIID, void **);     STDMETHODIMP_(ULONG) AddRef(void);     STDMETHODIMP_(ULONG) Release(void);     STDMETHODIMP GetMaxSpeed(*long *pn);     STDMETHODIMP Brake(void);       // composite to map distinguished IUnknown vptr to       // non-delegating InternalXXX routines 1n main object       //         vptr IUnknown       //       InternalXXX          //      class XNDUnknown : public IUnknown {         Car* This()            { return (Car*)((BYTE*)this - offsetof(Car, m_innerUnknown));}          STDMETHODIMP QueryInterface(REFIID r, void**p)            { return This()->InternalQueryInterface(r,p); }          STDMETHODIMP_(ULONG) AddRef(void)            { return This()->InternalAddRef(); }          STDMETHODIMP_(ULONG) Release(void)            { return This()->InternalRelease(); }     };     XNDUnknown m_innerUnknown;       // composite instance        //      };  . 4.8. :
 STDMETHODIMP Car::QueryInterface(REFIID riid, void **ppv)  {     return m_pUnkOuter->QueryInterface(riid, ppv);  } STDMETHODIMP_(ULONG) Car::AddRef(void)  {      return m_pUnkOuter->AddRef();  } STDMETHODIMP_(ULONG) Car::Release (void)  {      return m_pUnkOuter->Release();  }   
, vtbl , , IUnknown .
m_pUnkOuter , IUnknown:
 Car::Car(IUnknown *pUnkOuter) {     if (pUnkOuter)       // delegate to pUnkOuter        //     pUnkOuter         m_pUnkOuter = pUnkOuter;     else       // delegate to non-delegating self        //                m_pUnkOuter = &m_innerUnknown; }  , m_pUnkOuter QueryInterface, AddRef Release.
QueryInterface, AddRef Release :
 STDMETHODIMP Car::InternalQueryInterface(REFIID riid, void **ppv)  {     if (riid == IID_IUnknown)         *ppv = static_cast<IUnknown*>(&m_innerUnknown);     else if (riid = IID_IVehicle)         *ppv = static_cast<IVehicle*>(this);     else if (riid == IID_ICar)         *ppv = static_cast<ICar*>(this);     else         return (*ppv = 0), E_NOINTERFACE;     ((IUnknown*)*ppv)->AddRef();     return S_OK; }  STDMETHODIMP_(ULONG) Car::InternalAddRef(void)  {     return InterlockedIncrement(&m_cRef); }  STDMETHODIMP_(ULONG) Car::InternalRelease(void) {     ULONG res = InterlockedDecrement(&m_cRef);     if (res == 0) delete this;     return res; }  ( ) , InternalQueryInterface IUnknown Unknown. , .
, Car :
 STDMETHODIMP CarClass::CreateInstance(IUnknown *punk0uter, REFIID riid, void **ppv) {       // verify that aggregator only requests IUnknown as       // initial interface        //  ,         IUnknown        //          if (pUnkOuter != 0 && riid != IID_IUnknown)         return (*ppv = 0), E_INVALIDARG;       // create new object/aggregate        //              Car *  = new Car(pUnkOuter);     if (!p) return (*ppv = 0), E_OUTOFMEMORY;       // return resultant pointer       //          p->InternalAddRef();     HRESULT hr = p->InternalQueryInterface(riid, ppv);     p->InternalRelease();     return hr; }  , QueryInterface, AddRef Release. , , , . , , AddRef , . , IUnknown. . , vptr: QueryInterface, AddRef Release, . IUnknown vptr, IUnknown.
- , . , , AddRef. AddRef , AddRef, . , IUnknown ( , ) . IUnknown . . - , . , (identities) , .
, . , QueryInterface IUnknown. QueryInterface AddRef , AddRef. , , AddRef. , . , , :
 STDMETHODIMP Inner::MethodX(void)  {     ITruck *pTruck = 0;       // outer object will be AddRefed after this call...        //                      //     AddRef...      HRESULT hr = m_pUnkOuter->QueryInterface(IID_ITruck, (void**)&pTruck);     if (SUCCEEDED(hr)) {          pTruck->ShiftGears();         pTruck->HaulDirt();           // release reference to outer object            //                    pTruck->Release();     }  }  , .
 HRESULT Inner::Initialize(void)  {     // outer object will be AddRefed after this call...      //                    //     AddRef...      HRESULT hr = m_pUnkOuter->QueryInterface(IID_ITruck, (void**)&m_pTruck);     // release reference to outer object here and DO NOT      // release it later in the object's destructor      //                    //                    if (SUCCEEDED(hr))          m_pTruck->Release(); }  , . , m_pTruck . , ITruck , , Release .
, , , . , . , . , . , QueryInterface, AddRef , . , , , , , . , , , :
 Outer::Outer(void)  {     ++m_cRef;       // protect against delete this       //       this     CoCreateInstance(CLSID_Inner, this, CLSCTX_ALL,                       IID_IUnknown, (void**)&m_pUnkInner);     --m_cRef;       // allow delete this       //     this }  , , , , . , - (overridable), / . MFC (Microsoft Foundation Classes Microsoft) CreateAggregates, ATL FinalConstruct.
, C++, IMPLEMENT_UNKNOWN IUnknown. :
 class Car : public ICar {     Car(void);     IMPLEMENT_UNKNOWN(Car)      BEGIN_INTERFACE_TABLE(Car)     IMPLEMENTS_INTERFACE(ICar)     IMPLEMENTS_INTERFACE(IVehicle)     END_INTERFACE()       // IVehicle methods        //   IVehicle      STDMETHODIMP GetMaxSpeed(long *pn);       // ICar methods        //   ICar      STDMETHODIMP Brake(void); };  :
 class Car : public ICar {     Car(void);      //indicate that aggregation is required       //  ,            IMPLEMENT_AGGREGATABLE_UNKNOWN(Car)      BEGIN_INTERFACE_TABLE(Car)       IMPLEMENTS_INTERFACE(ICar)       IMPLEMENTS_INTERFACE(IVehicle)      END_INTERFACE()       // IVehicle methods        //   IVehicle      STDMETHODIMP GetMaxSpeed(long *pn);       // ICar methods        //   ICar      STDMETHODIMP Brake(void); };  IMPLEMENT_AGGREGATABLE_UNKNOWN , .
1 , (coloring) IUnknown. , , .