(精品)03Com接口与对象.ppt

上传人:hyn****60 文档编号:70981487 上传时间:2023-01-31 格式:PPT 页数:77 大小:254.50KB
返回 下载 相关 举报
(精品)03Com接口与对象.ppt_第1页
第1页 / 共77页
(精品)03Com接口与对象.ppt_第2页
第2页 / 共77页
点击查看更多>>
资源描述

《(精品)03Com接口与对象.ppt》由会员分享,可在线阅读,更多相关《(精品)03Com接口与对象.ppt(77页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、COM接口与对象接口与对象潘爱民北京大学计算机研究所2003-9-19http:/ IDLvvCOM对象从历史看从历史看COMvvCOM产生的背景9393年因为年因为OLE 2OLE 2的需要而产生的需要而产生OLE 1OLE 1的缺陷的缺陷vvCOM又从OLE中脱颖而出COMCOM的优势不限于的优势不限于OLEOLECOMCOM成为成为MicrosoftMicrosoft跟上跟上InternetInternet的一的一项重要基础技术项重要基础技术vv今天的Windows平台上,COM无处不在COMCOM和和.NETNETCOM基础基础三个概念三个概念vvCOM组件组件:可独立发布的二进制组件

2、组件:可独立发布的二进制组件在在WindowsWindows平台上为平台上为DLLDLL或者或者EXEEXEvvCOM对象通过通过COMCOM接口提供服务接口提供服务符合符合OOOO中对象的基本概念中对象的基本概念vvCOM接口客户与对象之间的协议,对象实现客户与对象之间的协议,对象实现COMCOM接口,客户使用接口,客户使用COMCOM接口接口如何设计?如何设计?vvCOM组件为方便起见,只讨论为方便起见,只讨论WindowsWindows平台上平台上DLLDLL类型的组件类型的组件vvCOM对象如何标识一个对象?对象以什么形式如何标识一个对象?对象以什么形式存在?客户如何创建对象?存在?客

3、户如何创建对象?对象如何暴露接口?一个或是多个?对象如何暴露接口?一个或是多个?vvCOM接口要求:跨编译器、跨语言、跨平台要求:跨编译器、跨语言、跨平台设计设计COM接口接口从从C+入手入手vvC+类:接口与实现的分离接口:类的接口:类的publicpublic部分部分class CMyStringprivate:char*m_psz;public:CMyString(const char*psz);CMyString();const char*Find(const char*psz);int Length();设计设计COM接口接口从从C+入手入手(续续)vvC+类的实现CMyString

4、:CMyString(const char*psz):m_psz(new charpsz?strlen(psz)+1:1)if(psz)strcpy(m_psz,psz);else m_psz0=0;CMyString:CMyString()delete m_psz;const char*CMyString:Find(const char*psz)return strstr(m_psz,psz);int CMyString:Length()return strlen(m_psz);C+类的链接类的链接(linking)vv静态链接许多类库的做法许多类库的做法编译时刻的链接编译时刻的链接vv静态

5、链接的缺点代码重复:多个程序各有自己的代码重复:多个程序各有自己的代码,需要更多的内存代码,需要更多的内存客户程序占据更多的外存空间客户程序占据更多的外存空间库代码更新需要重新编译所有的库代码更新需要重新编译所有的客户程序客户程序C+类的链接类的链接linking(续续)vv动态链接运行时刻的链接运行时刻的链接vv动态链接形式编译时刻通过引入库编译时刻通过引入库运行时刻完全动态运行时刻完全动态vvDll Hell#ifdef MYSTRINGDLL#define EXPORTORIMPORT _declspec(dllexport)#else#define EXPORTORIMPORT _de

6、clspec(dllimport)#endifclass EXPORTORIMPORT CMyStringprivate:char*m_psz;public:CMyString(const char*psz);CMyString();const char*Find(const char*psz);int Length();C+接口如何走向接口如何走向COM接口接口vv动态链接符合COM的需要vvC+中类形式的接口存在的问题客户看到了什么?客户看到了什么?若用若用Visual C+5.0/6.0Visual C+5.0/6.0编译器编译器?0CMyStringQAEPBDZ?1CMyString

7、QAEXZ?FindCMyStringQAEPBDPBDZ?LengthCMyStringQAEHXZ客户眼中的客户眼中的C+类类(续续)vv如果是Borland C+编译器(4.02)CMyString$bctr$qpxc CMyString$bdtr$qv CMyStringFind$qpxc CMyStringLength$qv vv问题1:名字冲突命名冲突解决方案命名冲突解决方案1vv模块定义文件(.def)中给出别名LIBRARY MYSTRINGEXPORTS CMyString$bctr$qpxc=?0CMyStringQAEPBDZ CMyString$bdtr$qv=?1CM

8、yStringQAEXZ CMyStringFind$qpxc=?FindCMyStringQAEPBDPBDZ CMyStringLength$qv=?LengthCMyStringQAEHXZ命名冲突解决方案命名冲突解决方案2vv模块定义文件(.def)中给出序号别名LIBRARY MYSTRINGEXPORTS?0CMyStringQAEPBDZ 1?1CMyStringQAEXZ 2?FindCMyStringQAEPBDPBDZ 3?LengthCMyStringQAEHXZ 4LIBRARY MYSTRINGEXPORTS CMyString$bctr$qpxc 1 CMyStri

9、ng$bdtr$qv 2 CMyStringFind$qpxc 3 CMyStringLength$qv 4命名冲突解决方案命名冲突解决方案3vv使用C+类的vtablevvC+类的vtable不随编译器而变化vvvtable包含了各个函数的原型,顺序固定,每个函数的参数、返回类型等,函数名并不重要vvvtable要求这些接口函数必须是虚函数vv客户如何得到vtable?仍然需要有一种办法来创建仍然需要有一种办法来创建C+C+类类new/deletenew/delete?需要对象的二进制结构需要对象的二进制结构问题问题2 2C+对象的二进制结构对象的二进制结构vvC+的封装是语法上的封装,而不

10、是二进制封装vvnew/delete是编译器相关的编译器不仅要知道编译器不仅要知道publicpublic信息,也要知道信息,也要知道privateprivate信息信息vvC+对象的二进制结构是编译器相关的vv即使客户看到的C+类公开接口没有变化,但是C+类的实现改变了,仍然会打破客户与对象之间的连接C+对象与客户之间的连接问题对象与客户之间的连接问题vv客户与C+对象之间的连接点越小越好只有接口部分必要的信息才放入接口只有接口部分必要的信息才放入接口把把C+C+类的实现细节与接口分开类的实现细节与接口分开提取出针对所有编译器都不变的因素作为提取出针对所有编译器都不变的因素作为客户与对象共享

11、的接口信息客户与对象共享的接口信息vv方案1:句柄句柄方案句柄方案vv方案1:句柄#ifndef CMyStringclass CMyString;#endifclass EXPORTORIMPORT IMyStringprivate:CMyString*m_pthis;public:IMyString(const char*psz);IMyString();const char*Find(const char*psz);int Length();class CMyStringprivate:char*m_psz;int m_nLength;public:CMyString(const cha

12、r*psz);CMyString();const char*Find(const char*psz);int Length();纯虚基类方案纯虚基类方案vv前提条件:在给定平台上所有的编译器都会产生同在给定平台上所有的编译器都会产生同样的二进制结构样的二进制结构纯虚函数在单继承情况下满足这一条件纯虚函数在单继承情况下满足这一条件vv纯虚基类只包含虚函数,限定每个虚函数的调用习惯vv对于跨平台的情形,我们肯定要通过中间层,所以暂时可以不考虑虚函数的继承布局情况虚函数的继承布局情况class B:class B:pulicpulic A A private:private:int int valu

13、e1;value1;public:public:virtual void Func1(void)virtual void Func1(void)virtual void Func2(void)virtual void Func2(void);变量 偏移量vptr 0value1 4B:Func1B:Func2vtable纯虚基类方案例子纯虚基类方案例子vv解决了名字冲突解决了名字冲突vv解决了解决了C+C+类的二进制布局不兼容问题类的二进制布局不兼容问题 客户只看到客户只看到vtablevtable,没有看到其他的实现细节没有看到其他的实现细节 保证不同语言编写的程序可以互操作保证不同语言编写

14、的程序可以互操作 在不改变接口的情况下,可以单独升级客户或者对象在不改变接口的情况下,可以单独升级客户或者对象class IString virtual const char*Find(const char*psz)=0;virtual int Length()=0;变量 偏移量 vptr 0FindLengthvtable纯虚接口的使用?纯虚接口的使用?vv假如有一个C+对象实现了IStringvv客户怎么使用?怎么拿到怎么拿到vtablevtable接口接口#include istring.hclass CMyString:public IStringprivate:char*m_psz;

15、public:CMyString(const char*psz);CMyString();const char*Find(const char*psz);int Length();如何创建对象?如何创建对象?vv不能使用newvvDLL的唯一接口是引出函数vv可行方案:单独提供一个引出函数供客户调用extern C _declspec(dllexport)IString*CreateString(const char*psz);extern C IString*CreateString(const char*psz)return new CMyString(psz);通过引出函数创建对象通过引

16、出函数创建对象extern C _declspec(dllimport)IString*CreateString(const char*psz);void main()IString*p;p=CreateString(Hello);if(p)const char*psz=p-Find(llo);int n=p-Length();创创建建对对象象#include istring.htypedef IString*(*PfnCreateString)(const char*psz);void main()IString*p;HANDLE h=LoadLibrary(c:tempmystring.d

17、ll);if(NULL!=h)PfnCreateString pfn=(PfnCreateString)GetProcAddress(h,CreateString);if(pfn)p=pfn(Hello);if(p)const char*psz=p-Find(llo);int n=p-Length();/Be careful about calling FreeLibrary.;如何删除对象?如何删除对象?vv删除对象发生在客户与对象建立联系之后,所以比较好办vv但是不能用deletevv可以让对象自己把自己删除vv在IString中增加一个方法class IString virtual vo

18、id Delete()=0;virtual const char*Find(const char*psz)=0;virtual int Length()=0;删除对象自身删除对象自身#include istring.hclass CMyString:public IStringprivate:char*m_psz;public:CMyString(const char*psz);virtual CMyString();void Delete();const char*Find(const char*psz);int Length();void CMyString:Delete()delete

19、this;#include istring.hvoid main()IString*p;p=CreateString(Hello);if(p)const char*psz=p-Find(llo);int n=p-Length();p-Delete();小结小结vv我们已经建立起对象与客户之间的基本通信方式vv更高的要求:接口的升级接口的升级增加新的功能增加新的功能生命周期管理生命周期管理vv什么时候该删除对象什么时候该删除对象vv多个客户共享同一个对象,如何管理?多个客户共享同一个对象,如何管理?对象的进化对象的进化vv在原有接口的基础上增加新的功能,例如class IString virtu

20、al void Delete();virtual const char*Find(const char*psz);virtual int Length();virtual char FindAt(int index);新客户老的对象对象的进化(续)对象的进化(续)vv完全增加新的功能class IPersist virtual void Delete();virtual void Save(const char*pszFile);virtual void Load(const char*pszFile);客户对象IStringIPersist?接口的进化接口的进化vv对象的接口不能发生变化如果

21、接口中需要增加新的方法,可以派生出如果接口中需要增加新的方法,可以派生出新的接口来新的接口来class IString2:public IStringvirtual char FindAt(int index);vv新对象实现两个接口:IString2和IString不打断新的客户与老的对象之间的关系不打断新的客户与老的对象之间的关系但是客户必须明确地知道对象是否实现了自但是客户必须明确地知道对象是否实现了自己感兴趣的接口己感兴趣的接口对象实现多个接口对象实现多个接口vv假如对象实现了两个接口IString和IPersist客户需要在客户需要在runtimeruntime时明确地知道接口的类型

22、时明确地知道接口的类型信息,包括通过创建函数得到的初始接口类型信息,包括通过创建函数得到的初始接口类型at runtimeat runtime,客户可以灵活地从一个接口变换客户可以灵活地从一个接口变换到另一个接口,如果对象不支持某个接口,客到另一个接口,如果对象不支持某个接口,客户也有办法知道户也有办法知道回忆回忆RTTI(Runtime type identification)RTTI(Runtime type identification)vvdynamic_castdynamic_castvvRTTIRTTI依赖于编译器的实现依赖于编译器的实现vvRTTIRTTI只能用于类的继承层次中只

23、能用于类的继承层次中对象实现多个接口对象实现多个接口(续一续一)vv所以我们需要自己构造一套类型机制,要求:每个接口都要提供类型转换机制,能转换到同每个接口都要提供类型转换机制,能转换到同一对象上实现的其他接口一对象上实现的其他接口客户只要得到了一个接口就可以得到其他的接客户只要得到了一个接口就可以得到其他的接口,所以创建函数可以返回任一个接口口,所以创建函数可以返回任一个接口如果对象不支持某个接口,客户必须能明确地如果对象不支持某个接口,客户必须能明确地知道,而不是发生异常知道,而不是发生异常 robustrobustDynamic_castDynamic_cast对象实现多个接口对象实现多

24、个接口(续二续二)vv一个对象实现IString2和IString接口:class IString virtual void Delete()=0;virtual void*Dynamic_cast(const char*psz)=0;virtual const char*Find(const char*psz)=0;virtual int Length()=0;class IString2:public IString virtual char FindAt(int index)=0;对象实现多个接口对象实现多个接口(续三续三)vv实现Dynamic_castclass CMyString:

25、public IString2.void*CMyString:Dynamic_cast(const char*psz)if(strcmp(psz,IString)=0)return static_cast(this);else if(strcmp(psz,IString2)=0)return static_cast(this);return NULL;对象实现多个接口对象实现多个接口(续四续四)#include istring.hvoid main()IString*p=CreateString(Hello);if(p)IString2*p2;const char*psz=p-Find(llo

26、);int n=p-Length();if(p2=(IString2*)p-Dynamic_cast(IString2)char c=p2-FindAt(3);p-Delete();class IPersist virtual void Delete()=0;virtual void*Dynamic_cast(const char*psz)=0;virtual void Save(const char*pszFile)=0;virtual void Load(const char*pszFile)=0;对象实现多个接口对象实现多个接口(续五续五)vv一个对象实现两个没有继承关系的接口#incl

27、ude istring.hclass CMyString:public IString2,public IPersist.void*CMyString:Dynamic_cast(const char*psz)if(strcmp(psz,IString)=0)return static_cast(this);else if(strcmp(psz,IString2)=0)return static_cast(this);else if(strcmp(psz,IPersist)=0)return static_cast(this);return NULL;对象实现多个接口对象实现多个接口(续六续六)

28、void main()IString*p=CreateString(Hello);if(p)IString2*p2;IPersist*p3;const char*psz=p-Find(llo);int n=p-Length();if(p2=(IString2*)p-Dynamic_cast(IString2)char c=p2-FindAt(3);if(p3=(IPersist*)p-Dynamic_cast(IPersist)p3-Save(c:tempstr.txt);p-Delete();对象实现多个接口对象实现多个接口(续七续七)接口的转换接口的转换vv每个接口提供一个用于接口转换的函

29、数vv对象实现接口的时候,可以使用C+编译器本身提供的类型转换功能vv每个接口的Dynamic_cast函数决定了客户可以访问其他哪些接口对象的生命周期管理对象的生命周期管理vv对象只需要被删除一次。每个接口都有对象只需要被删除一次。每个接口都有DeleteDelete函数?还是只有一个接口才有?进函数?还是只有一个接口才有?进一步,一步,什么时候删除对象?什么时候删除对象?vv客户可能拥有多个指向对象的引用,客户可能拥有多个指向对象的引用,每个每个引用各有自己的引用各有自己的lifetimelifetimevv每个引用从被有效赋值开始,一直到生命每个引用从被有效赋值开始,一直到生命周期结束,

30、这期间被称为:周期结束,这期间被称为:outstanding outstanding reference reference 未完结引用未完结引用vv客户管理每个引用的客户管理每个引用的lifetimelifetime,也就是说它也就是说它要要显式显式地告诉对象引用无效了地告诉对象引用无效了对象的生命周期管理对象的生命周期管理(续续)vv每个对象要管理一个被称为引用计数每个对象要管理一个被称为引用计数(reference count)reference count)的整数值。的整数值。vv为了有效地管理对象的生命周期,它应该提为了有效地管理对象的生命周期,它应该提供一些规则和操作,供客户遵守和

31、使用。供一些规则和操作,供客户遵守和使用。vv规则:保持引用计数的确切含义,也就是记规则:保持引用计数的确切含义,也就是记录当前录当前outstanding referenceoutstanding reference的数目。引用的数目。引用计数从计数从0 0开始,首次把接口递交给客户时为开始,首次把接口递交给客户时为1 1,以后由客户管理,当引用计数回到,以后由客户管理,当引用计数回到0 0时,时,删除自己。删除自己。vv当客户通过复制获得新的接口指针时,引用当客户通过复制获得新的接口指针时,引用计数加一,当某个接口不用时,减一计数加一,当某个接口不用时,减一引用计数的两个操作引用计数的两个

32、操作vv我们用引用计数我们用引用计数的两个管理操作的两个管理操作代替原来简单的代替原来简单的DeleteDelete函数函数class IString virtual void DestroyPointer()=0;virtual void*Dynamic_cast(const char*psz)=0;virtual void DuplicatePointer()=0;virtual const char*Find(const char*psz)=0;virtual int Length()=0;class IPersist virtual void DestroyPointer()=0;vi

33、rtual void*Dynamic_cast(const char*psz)=0;virtual void DuplicatePointer()=0;virtual void Save(const char*pszFile)=0;virtual void Load(const char*pszFile)=0;实现引用计数的两个操作实现引用计数的两个操作CMystring:CMyString(const char*psz):m_psz(new charpsz?strlen(psz)+1:1),m_refcount(0)if(psz)strcpy(m_psz,psz);else m_psz0=0

34、;void CMyString:DestroyPointer()if(0m_refcount)m_refcount-;if(0=m_refcount)delete this;void CMyString:DuplicatePointer()m_refcount+;#include istring.hclass CMyString:public IString2,public IPersistprivate:char*m_psz;long m_refcount;public:CMyString(const char*psz);CMyString();void DuplicatePointer()

35、;void DestroyPointer();void*Dynamic_cast(const char*);const char*Find(const char*psz);int Length();char FindAt(int index);void Save(const char*pszFile);void Load(const char*pszFile);接口转换时刻相当于接口复制接口转换时刻相当于接口复制void*CMyString:Dynamic_cast(const char*psz)void*p=NULL;if(strcmp(psz,IString)=0)p=static_cas

36、t(this);else if(strcmp(psz,IString2)=0)p=static_cast(this);else if(strcmp(psz,IPersist)=0)p=static_cast(this);if(NULL!=p)m_refcount+;return p;客户管理对象的生命周期客户管理对象的生命周期void main()IString*p=CreateString(Hello);if(p)IString2*p2;IPersist*p3;const char*psz=p-Find(llo);int n=p-Length();if(p2=(IString2*)p-Dyn

37、amic_cast(IString2)char c=p2-FindAt(3);p2-DestroyPointer();if(p3=(IPersist*)p-Dynamic_cast(IPersist)p3-Save(c:tempstr.txt);p3-DestroyPointer();p-DestroyPointer();extern C void*CreateString(const char*psz,const char*pszinterface)void*pret=NULL;CMyString*p=new CMyString(psz);if(NULL!=p)pret=p-Dynamic_

38、cast(pszinterface);if(NULL=pret)delete p;return pret;修改创建函数修改创建函数vv让创建函数也正确地维护引用计数接口整理接口整理vv每个接口都需要下面的三个函数Dynamic_castDynamic_castDuplicatePointerDuplicatePointerDeletePointerDeletePointervv把三个函数放到一个基接口中,所有的接口都从这个基接口派生class IAnyInterfacevirtual void*DynamicCast(const char*psz)=0;virtual void Duplica

39、tePointer()=0;virtual void DestroyPointer()=0;其他尚待考虑的问题其他尚待考虑的问题vvDll什么时候被卸载?vv如何标识一个接口?字符串?vv线程安全?vv如何标识一个对象?对象的身份?vv跨进程?跨机器?对象环境?vvCOM接口接口vv概念:函数集,以二进制的形式给出了从一方到另一方的调用规范vv接口标识IIDvvIUnknownvvCOM接口二进制结构COM接口的标识接口的标识IIDvv是是GUIDGUID的一种用法的一种用法vvGUIDGUID是一个是一个128128位的长整数位的长整数vv产生规则保证了唯一性产生规则保证了唯一性vv例子:例

40、子:5454BF6567-1007-11D1-B0AA-444553540000BF6567-1007-11D1-B0AA-444553540000vvC C语言结构和定义:语言结构和定义:typedef structtypedef struct _GUID _GUID DWORD DWORD Data1;Data1;WORD WORD Data2;Data2;WORD WORD Data3;Data3;BYTE BYTE Data48;Data48;GUID;GUID;extern C const GUID CLSID_MYSPELLCHECKER=extern C const GUID C

41、LSID_MYSPELLCHECKER=0 x54bf6567,0 x1007,0 x11d1,0 x54bf6567,0 x1007,0 x11d1,0 xb0,0 xaa,0 x44,0 x45,0 x53,0 xb0,0 xaa,0 x44,0 x45,0 x53,0 x54,0 x00,0 x00 ;0 x54,0 x00,0 x00 ;IUnknown接口接口vv所有的COM接口都从IUnknown派生vvC+定义:class class IUnknown IUnknown public:public:virtual HRESULT_virtual HRESULT_stdcall Q

42、ueryInterfacestdcall QueryInterface(const IID&const IID&iidiid,void*,void*ppvppv)=0;)=0;virtual ULONGvirtual ULONG _ _stdcall AddRefstdcall AddRef()=0;()=0;virtual ULONGvirtual ULONG _ _stdcall stdcall Release()=0;Release()=0;IUnknown接口接口(续续)vvC定义:typedef struct IUnknownVtbltypedef struct IUnknownVt

43、bl HRESULT(STDMETHODCALLTYPE _RPC_FAR*HRESULT(STDMETHODCALLTYPE _RPC_FAR*QueryInterfaceQueryInterface )()(IUnknownIUnknown _RPC_FAR*This,/*in*/REFIID _RPC_FAR*This,/*in*/REFIID riidriid,/*/*iidiid_isout*/void _RPC_FAR*_RPC_FAR*_isout*/void _RPC_FAR*_RPC_FAR*ppvObjectppvObject););ULONG(STDMETHODCALLT

44、YPE _RPC_FAR*ULONG(STDMETHODCALLTYPE _RPC_FAR*AddRefAddRef)()(IUnknownIUnknown _RPC_FAR*This);_RPC_FAR*This);ULONG(STDMETHODCALLTYPE _RPC_FAR*ULONG(STDMETHODCALLTYPE _RPC_FAR*ReleaseRelease)()(IUnknownIUnknown _RPC_FAR*This);_RPC_FAR*This);IUnknownVtblIUnknownVtbl;interface interface IUnknownIUnknow

45、n CONST_VTBL CONST_VTBL struct IUnknownVtblstruct IUnknownVtbl _RPC_FAR*_RPC_FAR*lpVtbllpVtbl;COM接口结构接口结构C语言描述示例语言描述示例IDictionarystruct IDictionaryVtblstruct IDictionaryVtbl;struct IDictionarystruct IDictionary IDictionaryVtblIDictionaryVtbl*pVtblpVtbl;struct IDictionaryVtblstruct IDictionaryVtbl/*/

46、*QueryInterfaceQueryInterface,AddRefAddRef,Release*/,Release*/BOOL(*Initialize)(BOOL(*Initialize)(IDictionaryIDictionary*this);*this);BOOL(*BOOL(*LoadLibraryLoadLibrary)()(IDictionaryIDictionary*this,String);*this,String);BOOL(*BOOL(*InsertWordInsertWord)()(IDictionaryIDictionary*this,String,String)

47、;*this,String,String);void (*void (*DeleteWordDeleteWord)()(IDictionaryIDictionary*this,String);*this,String);BOOL(*BOOL(*LookupWordLookupWord)()(IDictionaryIDictionary*this,String,String*);*this,String,String*);BOOL(*BOOL(*RestoreLibraryRestoreLibrary)()(IDictionaryIDictionary*this,String);*this,St

48、ring);void (*void (*FreeLibraryFreeLibrary)()(IDictionaryIDictionary*this);*this);C+语言描述示例语言描述示例IDictionaryclass class IDictionaryIDictionary:public :public IUnknownIUnknown virtual BOOL Initialize()=0;virtual BOOL Initialize()=0;virtual BOOL virtual BOOL LoadLibraryLoadLibrary(String)=0;(String)=0;

49、virtual BOOL virtual BOOL InsertWordInsertWord(String,String)=0;(String,String)=0;virtual void virtual void DeleteWordDeleteWord(String)=0;(String)=0;virtual BOOL virtual BOOL LookupWordLookupWord(String,String*)=0;(String,String*)=0;virtual BOOL virtual BOOL RestoreLibraryRestoreLibrary(String)=0;(

50、String)=0;virtual void virtual void FreeLibraryFreeLibrary()=0;()=0;COM接口的内存模型接口的内存模型COM接口的内存模型接口的内存模型(续一续一)COM接口的内存模型接口的内存模型(续二续二)接口查询接口查询vv目的:按照COM规范,一个COM对象可以实现多个接口。从一个接口到另一个接口的访问途径vv函数QueryInterface(iid,ppv)vv用法:初始得到了一个接口指针之后,调用它的初始得到了一个接口指针之后,调用它的QueryInterfaceQueryInterface函数,获得另一个接口指针函数,获得另一个

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 生活休闲 > 生活常识

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁