首页 > 编程知识 正文

接口和函数的区别,接口interface是指

时间:2023-05-04 21:41:41 阅读:62487 作者:4802

通过:IUnKNown接口——查询接口函数

所有客户和组件的交互都在一个界面上进行。 客户查询组件的其他接口时,也通过接口进行。 这个接口就是IUnknown。 这是在UNKNWN.H头文件中定义的。 如下所示

接口{ virtual hresult _ _ stdcallqueryinterface,void**PPVobject}=0; virtual ulong _ _ stdcall addref (void )=0; virtual ulong _ _ stdcall release (void )=0; }所有COM接口都继承了IUnknown,每个接口的vtbl的前三个函数是QueryInterface、AddRef和Release (图3-1 )。 这样,所有COM接口都可以视为IUnknown接口。

因为所有接口都是从IUnknown继承的,所以所有接口都支持查询接口,所以组件中的任何接口都可以由客户用来获取其他受支持的接口

查询接口I unknown的成员函数查询接口。 可以使用此函数来查询组件是否支持特定接口。 如果支持QueryInterface,则返回指向若干接口的指针,不支持的返回值为错误代码。 查询界面有两个参数和一个HRESULT返回值

hresult _ _ stdcallqueryinterface (refiidriid,void * * PPV对象);

第一个参数:接口标识符(IID; 第二个参数是存储所请求接口指针的地址。 返回值:如果查询成功,则返回S_OK;如果查询失败,则返回错误代码。

使用查询界面定义voidfoo(Iunknown*pi )//接口指针IX* pIX=NULL; //查询接口ixhresulthr=pi-query接口(iid _ IX,) void * * (pix ); 安全(HR )//接口到函数pIX-Fx ); }

查询接口实现

根据指定的IID返回指向相应接口的指针。 如果组件支持客户指定的接口,则必须返回到S_OK和相应的指针。 如果返回测试不支持返回e _ no接口,则将相应指针的返回值设置为NULL。

QueryInterface实现要求允许将一个类型映射到另一个类型的结构。 例如,可以在if else、数组、哈希表或树中实现,但不能使用case语句。 因为接口标识符是结构,而不是数量。

注意: IX和IY不能虚拟继承IUnknown。 否则,IX和vtbl的前三个函数指向的不是IUnknown的三个成员函数。

hresult _ stdcall ca :3360 query interface (一致性,void** ppv ) if ) iid==iid_Iunknown (跟踪) quace ) ) }elseif(iid==iid_IX ) ) trace (' query interface : returnpointertoix.' ); *PPV=static_castix*(this; }elseif(iid==iid_iy )跟踪(' query interface : returnpointertoiy.' ); *ppv=static_castIY*(this ); } else { trace (' query interface : interfacenotsupported.'; * PPV=空; return e _ no接口;

} reinterpret_cast<IUnknown*>(*ppv)->AddRef(); return S_OK;}

IUnknown

接口标准化,在COM中有两方面的内容:一是接口基本功能的标准化,二是接口内存结构的标准化。为了保证组件接口在基本功能上的标准化,COM预定义了一个基本接口IUnknow。(在文件UNKNWN.H中定义)

Class Iunknown{ Public: Virtual HRESULT _stdcall QueryInterface(const IID& iid, void **ppv)=0; Virtual HRESULT _stdcal AddRef( )=0; Virtual HRESULT _stdcal Release( )=0;};显然,Iunknown接口具有3个纯虚函数。COM 要求组件的所有接口必须继承自IUnknown接口,这样就保证组件的所有接口都能提供这3个服务(函数)。

一个完整的例子 #include <iostream>using namespace std;#include <objbase.h>void trace(const char* msg) { cout << msg << endl;}// 接口定义interface IX : IUnknown{ virtual void __stdcall Fx() = 0;};interface IY : IUnknown{ virtual void __stdcall Fy() = 0;};interface asjdh : IUnknown{ virtual void __stdcall Fz() = 0;};// Forward references for GUIDsextern const IID IID_IX;extern const IID IID_IY;extern const IID IID_asjdh;//// 实现接口 IX,IY(这里表示一个组件)//class CA : public IX, public IY{ //IUnknown implementation virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv); virtual ULONG __stdcall AddRef() { return 0;} virtual ULONG __stdcall Release() { return 0;} // Interface IX implementation virtual void __stdcall Fx() { cout << "这里是Fx函数" << endl;} // Interface IY implementation virtual void __stdcall Fy() { cout << "这里是Fy函数" << endl;}};HRESULT __stdcall CA::QueryInterface(const IID& iid, void** ppv){ if (iid == IID_IUnknown) { trace("QueryInterface: Return pointer to IUnknown."); *ppv = static_cast<IX*>(this); } else if (iid == IID_IX) { trace("QueryInterface: Return pointer to IX."); *ppv = static_cast<IX*>(this); } else if (iid == IID_IY) { trace("QueryInterface: Return pointer to IY."); *ppv = static_cast<IY*>(this); } else { trace("QueryInterface: Interface not supported."); *ppv = NULL; return E_NOINTERFACE; } reinterpret_cast<IUnknown*>(*ppv)->AddRef(); // 加计数 return S_OK;}//// 创建类CA,并返回一个指向IUnknown的指针//IUnknown* CreateInstance(){ IUnknown* pI = static_cast<IX*>(new CA); pI->AddRef(); return pI ;}//// 下面是各接口的IID//// {32bb8320-b41b-11cf-a6bb-0080c7b2d682}static const IID IID_IX = {0x32bb8320, 0xb41b, 0x11cf,{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};// {32bb8321-b41b-11cf-a6bb-0080c7b2d682}static const IID IID_IY = {0x32bb8321, 0xb41b, 0x11cf,{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};// {32bb8322-b41b-11cf-a6bb-0080c7b2d682}static const IID IID_asjdh = {0x32bb8322, 0xb41b, 0x11cf,{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};//// 主函数(这里代表客户)//int main(){ HRESULT hr; trace("Client:获取 IUnknown指针."); IUnknown* pIUnknown = CreateInstance(); trace("Client:获取接口IX."); IX* pIX = NULL; hr = pIUnknown->QueryInterface(IID_IX, (void**)&pIX); if (SUCCEEDED(hr)) { trace("Client:获取接口IX成功."); pIX->Fx(); // 使用 IX. } trace("Client:获取接口IY."); IY* pIY = NULL; hr = pIUnknown->QueryInterface(IID_IY, (void**)&pIY); if (SUCCEEDED(hr)) { trace("Client: Succeeded getting IY."); pIY->Fy(); // 使用 IY. } trace("Client:是否支持接口asjdh."); asjdh* pasjdh = NULL; hr = pIUnknown->QueryInterface(IID_asjdh, (void**)&pasjdh); if (SUCCEEDED(hr)) { trace("Client:获取接口asjdh成功."); pasjdh->Fz(); } else { trace("Client:获取接口asjdh失败,不支持接口asjdh."); } trace("Client:用接口IX查询接口IY."); IY* pIYfromIX = NULL; hr = pIX->QueryInterface(IID_IY, (void**)&pIYfromIX); if (SUCCEEDED(hr)) { trace("Client:获取接口IY成功."); pIYfromIX->Fy(); } trace("Client:用接口IY查询接口IUnknown."); IUnknown* pIUnknownFromIY = NULL; hr = pIY->QueryInterface(IID_IUnknown, (void**)&pIUnknownFromIY); if (SUCCEEDED(hr)) { cout << "IUnknown指针是否相等?"; if (pIUnknownFromIY == pIUnknown) { cout << "Yes, pIUnknownFromIY == pIUnknown." << endl; } else { cout << "No, pIUnknownFromIY != pIUnknown." << endl; } } // Delete the component. delete pIUnknown; return 0;}
QueryInterface的实现规则

1.QueryInterface返回的总是同一IUnknown指针。
2.若客户曾经获取过某个接口,那么将总能获取此接口。如果曾经不能,则将总是不能。
3.客户可以再次获取已经拥有的接口。
4.客户可以返回到接口。
5.若能够从某个接口获取某特定接口,那么可以从任意接口都将可以获取此接口。

同一IUnknown指针:
组件的实例只有一个IUnknown接口。因为查询组件实例的IUnknown接口时,不论通过哪个接口,所得到的均将是同一指针值。所以可以通过两个接口的IUnknown,然后比较他们的值。看看是否相同来判断两个接口是否在同一个组件里。
BOOL SameComponents(IX* pIX, IY* pIY){ IUnknown* pI1 = NULL; IUnknown* pI2 = NULL; pIX->QueryInterface(IID_IUnknown, (void**)&pI1); pIY->QueryInterface(IID_IUnknown, (void**)&pI2); return pI1 == pI2;} QueryInterface定义了组件

一个组件实际上就是由QueryInterface定义的。组件所支持的接口集就是QueryInterface能够为之返回接口指针的那些接口。这一点是由QueryInterface的实现决定的,而不是由实现组伯的C++类决定的。实现组件的类的继承层次关系也不能决定组件。



版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。