(精品)03Com接口与对象.ppt
《(精品)03Com接口与对象.ppt》由会员分享,可在线阅读,更多相关《(精品)03Com接口与对象.ppt(77页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
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
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 精品 03 Com 接口 对象
限制150内