网站大量收购闲置独家精品文档,联系QQ:2885784924

接口的其他实现方法.ppt

  1. 1、本文档共50页,可阅读全部内容。
  2. 2、有哪些信誉好的足球投注网站(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
  3. 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  4. 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
六 . COM接口的其他实现方法 基于表格驱动的接口查询 接口查询的本质 宏 应用 多重继承下的名字冲突 潜在的缺陷 临时的方案 使用复合技术(嵌套类)实现接口 COM主对象和COM子对象 COM 主对象的实现 COM 子对象的实现 基于复合技术的COM对象的内存结构 1.基于表格驱动的接口查询 1.1 接口查询的本质 前面我们使用继承的方式实现接口,使用多重继承的方式实现多个接口. 在这种方式下,接口的查询QueryInterface函数的实现非常的直接且直观. 在多重继承方式下,接口类是基类, IUnkown接口是最上层的基类. 对象类是接口类的派生的子类. 在内存中,子类比基类“大”. 因为子类除了包含基类的成员以外,还包含自己的成员.子类的一个实例中包含有基类的一个“subobject”,子对象. 如果这个基类还有基类,这个子对象中还含有一个更上层的子对象. QueryInterface函数的本质是: 使用statice_cast操作符在子类的对象中加上基类的偏移从而从而得到基类的子对象.转换到不同的基类时,要加上不同的偏移. 所以QueryInterface实际上是在不同的基类和不同的偏移中工作. 我们可以把基类和对应的偏移量抽象出来.作成表格.使得QueryInterface的工作更加形式化. 最终使得COM的编码更加形式化. (这里的工作为向MFC过渡而热身.我们看到,MFC中古怪的代码也是有其理性的由来的.? ) 1.2 宏 为了实现表格驱动的QueryInterface, 我们定义这样的一个结构: typedef HRESULT (STDAPICALLTYPE *INTERFACE_FINDER)(void *pThis, DWORD dwData, REFIID riid, void **ppv); //这是一个查询接口的函数,暂时这里并没有用上. #define ENTRY_IS_OFFSET INTERFACE_FINDER(-1) //所以这里定义了一个伪函数ENTRY_IS_OFFSET typedef struct _INTERFACE_ENTRY { const IID * pIID; // 要寻找的接口的IID INTERFACE_FINDER pfnFinder; // finder function long dwData; // finder function所需的参数.这里指偏移量. } INTERFACE_ENTRY; //暂时,这里只使用了第一和第三个分量 然后定义了几个宏: #define BASE_OFFSET(ClassName, BaseName) \ (DWORD(static_castBaseName*(reinterpret_castClassName*(0)) - 0 这个宏用来计算基类BaseName到子类ClassName的偏移.(一个完整对象中的基类子对象的起始地址到完整对象的起始地址的偏移) reinterpret_castClassName*(0 把绝对内存地址0换成为子类对象的地址. static_castBaseName*(子类指针) 把子类指针转换为基类指针.这个工作由编译器计算出偏移.并且加上偏移值. DWORD(基类指针地址) - 0基类指针地址转换成绝对的数字后减去子类指针的绝对地址的数字. 宏BASE_OFFSET(ClassName, BaseName) 返回基类BaseName到子类ClassName的偏移量. 如下图所示: 在这个宏的基础上又定义了几个宏: #define BEGIN_INTERFACE_TABLE(ClassName) \ typedef ClassName _InterfaceTableClassName;\ //申明了一个静态函数,返回接口表 static const INTERFACE_ENTRY *GetInterfaceTable(void) \ { static const INTERFACE_ENTRY table[] = {\ //函数体中, 定义一个静态的接口表, 定义了类,此表就分配了.对所有的对象而言是同一个. #define IMPLEMENTS_INTERFACE(ItfName) \ { IID_##ItfName, ENTRY_IS_OFFSET, BASE_OFFSET(_InterfaceTableClassName, ItfName) }, //接口表项,对于接口I

文档评论(0)

zhuliyan1314 + 关注
实名认证
内容提供者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档