首页 > 代码库 > QueryInterface

QueryInterface

  1 // 08win32console-ATL.cpp : 定义控制台应用程序的入口点。
  2 //
  3 
  4 
  5 #include "stdafx.h"
  6 #include <objbase.h>
  7 #include <iostream>
  8 
  9 using std::cout;
 10 using std::endl;
 11 
 12 // {4FD945C1-9258-40d6-8370-738EF039C73D}
 13 static const IID IID_IX = 
 14 { 0x4fd945c1, 0x9258, 0x40d6, { 0x83, 0x70, 0x73, 0x8e, 0xf0, 0x39, 0xc7, 0x3d } };
 15 
 16 // {5765B41E-C0E5-47a2-81AF-ED8E5981327E}
 17 static const IID IID_IY = 
 18 { 0x5765b41e, 0xc0e5, 0x47a2, { 0x81, 0xaf, 0xed, 0x8e, 0x59, 0x81, 0x32, 0x7e } };
 19 
 20 // {81E64914-44CF-43e3-9660-E5AB7C64B045}
 21 static const IID IID_IZ = 
 22 { 0x81e64914, 0x44cf, 0x43e3, { 0x96, 0x60, 0xe5, 0xab, 0x7c, 0x64, 0xb0, 0x45 } };
 23 
 24 
 25 void trace(const char *pMsg) {cout << pMsg << endl;}
 26 
 27 interface IX : IUnknown{
 28     virtual void __stdcall Fx() = 0;
 29 };
 30 
 31 interface IY : IUnknown{
 32     virtual void __stdcall Fy() = 0;
 33 };
 34 
 35 interface IZ : IUnknown{
 36     virtual void __stdcall Fz() = 0;
 37 };
 38 
 39 class CA : public IX, public IY
 40 {
 41     virtual HRESULT __stdcall QueryInterface(const IID & iid, void ** ppv);
 42     virtual ULONG __stdcall AddRef() {return 0;}
 43     virtual ULONG __stdcall Release() {return 0;}
 44 
 45     virtual void __stdcall Fx() {cout << "CA::Fx" << endl;}
 46     virtual void __stdcall Fy() {cout << "CA::Fy" << endl;}
 47 };
 48 
 49 HRESULT __stdcall CA::QueryInterface(const IID & iid, void ** ppv)
 50 {
 51     if (iid == IID_IUnknown)
 52     {
 53         trace("QueryInterface: return pointer to IUnknown");
 54         *ppv = static_cast<IX *>(this); 
 55     }
 56     else if (iid == IID_IX)
 57     {
 58         trace("QueryInterface: return pointer to IX");
 59         *ppv = static_cast<IX *>(this);
 60     }
 61     else if (iid == IID_IY)
 62     {
 63         trace("QueryInterface: retrun pointer to IY");
 64         *ppv = static_cast<IY *>(this);
 65     }
 66     else
 67     {
 68         trace("QueryInterface: Interface not support");
 69         *ppv = NULL;
 70         return E_NOINTERFACE;
 71     }
 72     reinterpret_cast<IUnknown*>(*ppv)->AddRef();
 73 
 74     return S_OK;
 75 }
 76 
 77 IUnknown* CreateInstance()
 78 {
 79     IUnknown* pI = static_cast<IX *>(new CA);
 80     pI->AddRef();
 81     return pI;
 82 }
 83 
 84 int main()
 85 {
 86     HRESULT hr;
 87     trace("Client: Get an IUnknown pointer.");
 88     IUnknown * pUInknown = CreateInstance();
 89     
 90     trace("Client: Get interface IX.");
 91     IX * pIX = NULL;
 92     hr = pUInknown->QueryInterface(IID_IX, (void **)&pIX);
 93     if (SUCCEEDED(hr))
 94     {
 95         trace("Client: Succeeded getting IX");
 96         pIX->Fx();
 97     }
 98     
 99     trace("Client: Get interface IY.");
100     IY * pIY = NULL;
101     hr = pUInknown->QueryInterface(IID_IY, (void **)&pIY);
102     if (SUCCEEDED(hr))
103     {
104         trace("Client: Succeeded getting IY");
105         pIY->Fy();
106     }
107     
108     trace("Client: Get interface IZ");
109     IZ * pIZ = NULL;
110     hr = pUInknown->QueryInterface(IID_IZ, (void **)&pIZ);
111     if (FAILED(hr))
112     {
113         trace("Client: Cannot get interface IZ");
114     }
115     
116     trace("Client: Get interface IY from interface IX.");
117     IY * pIYfromIX = NULL;
118     hr = pIX->QueryInterface(IID_IY, (void **)&pIYfromIX);
119     if (SUCCEEDED(hr))
120     {
121         trace("Client: Succeeded getting IY");
122         pIYfromIX->Fy();
123     }
124     
125     trace("Client: Get interface IUnknown from IY");
126     IUnknown * pIUnknownfromIY = NULL;
127     hr = pIY->QueryInterface(IID_IUnknown, (void **)&pIUnknownfromIY);
128     if (SUCCEEDED(hr))
129     {
130         trace("Are the IUnknown pointers equal");
131         if (pIUnknownfromIY == pUInknown)
132             trace("Yes");
133         else
134             trace("No");
135     }
136     
137     delete pUInknown;
138     getchar();
139     return 0;
140 }

 

 

从其他任何接口都可以通过QueryInterface来实现CA所实现的任何接口

 

组件的实例只有一个IUnknown接口,因此要知道两个接口是否指向同一组件,只需通过这两个接口查询IUnknown接口,然后比较返回值即可。

 

C++相当于面试,基本情况简历一目了然

COM相当于社交,只有通过询问获取了解

客户无法获得COM的全部细节,不让客户了解COM的身份特征,可以使客户尽可能少的受组件改变的影响。

 

组件通过AddRef 和 Release来管理自己的生命周期(引用计数)

复制接口指针之后应该增加其引用计数