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来管理自己的生命周期(引用计数)
复制接口指针之后应该增加其引用计数