资源描述
,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,*,COM,COM,第一个,COM,对象,例子,(G:File,内部交流,赵国光,comExampleDropTarget),IDropTarget,的定义,interface,IDropTarget:,public,IUnknown,public,:,virtual,HRESULT STDMETHODCALLTYPE,DragEnter,(,/*uniquein*/IDataObject _RPC_FAR*pDataObj,/*in*/DWORD grfKeyState,/*in*/POINTL pt,/*outin*/DWORD _RPC_FAR*pdwEffect)=0;,virtual,HRESULT STDMETHODCALLTYPE,DragOver,(,/*in*/DWORD grfKeyState,/*in*/POINTL pt,/*outin*/DWORD _RPC_FAR*pdwEffect)=0;,virtual,HRESULT STDMETHODCALLTYPE,DragLeave,(void)=0;,virtual,HRESULT STDMETHODCALLTYPE,Drop,(,/*uniquein*/IDataObject _RPC_FAR*pDataObj,/*in*/DWORD grfKeyState,/*in*/POINTL pt,/*outin*/DWORD _RPC_FAR*pdwEffect)=0;,;,第一个COM对象例子(G:File内部交流赵国光co,什么是,COM,Component Object Model(组件对象模型),微软提出的二进制上的组件标准,定义了对象(组件)之间进行通信的协议。,COM是一个更好的C+,什么是COMComponent Object Model(组,C+,库厂商的麻烦,某一个,c+,库厂商开发生产了一个算法,可以在,O(1),时间阶内完成字符串搜索。,为了让客户能够简单的使用这个算法,库厂商创建了一个类:,FastString,示例:,faststring.h,faststring.cpp,C+库厂商的麻烦某一个c+库厂商开发生产了一个算法,可以,软件分发,传统上,库厂商分发,C+,库一直以源码的形式进行,.,问题:,代码复制,多个应用使用相同的代码占用磁盘空间以及内存,.,代码更新,将源码重新分发,重新编译链接,失去了模块化的特征,.,软件分发传统上,库厂商分发C+库一直以源码的形式进行.,示意图,应用,A,应用,C,应用,B,FastString.obj,FastString.obj,FastString.obj,示意图 应用A 应用C 应用BFastString.objF,动态链接库,(dll),为了解决重复代码以及更新困难的问题,将FastString类封装为一个dll是一个马上想到的方法.,_declspec(dllexport)关键字.,引入库(import library),动态链接库(dll)为了解决重复代码以及更新困难的问题,将F,示意图,应用,A,应用,C,应用,B,FastString.dll,Dll,引入库,示意图应用A应用C应用BFastString.dllDll引,C+,的可移植性,C+,缺少二进制级别的标准,编译器和链接器的兼容性,名字的问题,链接时表达符号名字,为了支持函数重载和操作符重载,不同的编译器,/,链接器会任意修改入口点的符号名字,称为名字改编,(name,mangling),使用,extern,“C”,可以消除名字改编现象,但只对全局函数有效,.,使用模块定义文件,(Module,Definition File DEF).,在运行时表达语言的不同特征,编译器厂商对语言的特征有不同方式的实现,异常,(Exception),是一个例子,.,C+的可移植性C+缺少二进制级别的标准,封装性的问题,假如已经解决了编译器和链接器的问题,建立二进制组件的下一个障碍则和封装有关,.,FastString,的,Length,方法有问题,修改,FastString,类的定义,.,FastString,dll,升级为,2.0,解决,Length,的问题,.,FastString,Dll,分版本改名策略,.,新应用,(,用修改后的,FastString,),旧应用,FastString.dll(2.0),封装性的问题假如已经解决了编译器和链接器的问题,建立二进制组,接口与实现的分离,封装的基础,在,C+,中,这个原则没有应用到二进制层,因为,C+,类即是接口也是实现,.,如何做到接口与实现的分离,将接口与实现分立成两个实体,在,c+,中表现为两个类,接口类和实现类,.,接口类只对一定的数据类型进行描述,.,实现类对数据类型作具体的实现,.,接口类的定义,接口与实现的分离封装的基础,faststringitf.h,class,FastString,;,class,_declspec,(,dllexport,)FastStringInf,private,:,FastString,*m_pObj;,public,:,FastStringInf(,const,char,*psz);,FastStringInf();,int,Length(),const,;,int,Find(,const,char,*,psz)const,;,;,示例:,G:File,内部交流,赵国光,comExamplefaststringdll2,faststringitf.hclass FastStrin,使用面向对象的特性,编译器,/,链接器的问题依然没有解决。,利用所有编译器,/,链接器的一致性。,复合结构在运行时表现形式对不同编译器一致,.,所有编译器使用相同的堆栈规则传递参数,.,所有,C+,编译器实现相同的虚函数调用机制,.,也就是说对每个,c+,编译器来说,一个对象在内存中如何表示,以及在运行时怎样调用虚函数都必须一致,以上三条假设所有编译器必须要遵从,.,使用面向对象的特性编译器/链接器的问题依然没有解决。,使用抽象基类作为二进制接口,vptr,以及,vtbl,adjustor thunk(win32),CFRONT(solaris),vptr,v_fun1,v_fun2,v_fun3,vtbl,使用抽象基类作为二进制接口vptr以及vtblvptrv_f,IFastString/,接口,FastString,的抽象基类,class,IFastString,public,:,virtual,int,Length(),const,=0;,virtual,int,Find(,const,char,*psz),const,=0;,;,vptr,Length,Find,vtbl,IFastString,内存结构,IFastString/接口FastString的抽象基类v,FastString/,实现,class,FastString,public,:IFastString,private,:,const,int,m_cch;,char,*,m_psz;,public,:,FastString(,const,char,*psz);,FastString(,void,);,int,Length(,void,),const,;,int,Find(,const,char,*psz),const,;,;,vptr,Length,Find,vtbl,FastString,内存结构,m_cch,m_psz,FastString/实现class FastString,唯一的全局函数,extern,“C”IFastString*CreateFastStringObject(,const char,*,psz),return new,FastString(psz);,new,方法在,dll,内部被调用。,唯一的全局函数extern“C”IFastString,析构函数的问题,考虑如下用法:,IFastString,*fs=CreateFastStringObject(“hellow everyone”);,if,(fs),int,pos=fs-Find(“very”);,delete,fs;,问题:内存泄露。,原因:,IFastString,的析构函数并不是虚函数。,解决办法:显示的使用删除方法删除自身。,示例:,G:File,内部交流,赵国光,comExamplefaststringdll3,析构函数的问题考虑如下用法:,动态载入,dll,的好处,减少应用程序初始化的工作。,dll,不存在也不会导致系统出现错误。,在运行时动态选择不同的实现。,(,另外的意义是组件升级,),动态载入dll的好处减少应用程序初始化的工作。,功能升级扩展带来的问题,接口的改变或增加都可能导致客户代码重新编译。,class,IFastString,public:,virtual,int,Delete(void),=,0;,virtual,int,Length(),const,=0;,virtual,int,Find(,const,char,*psz),const,=0;,/,新功能,virtual int,FindN(const char*psz),const,=0;,新方法追加在接口定义的尾部,老客户使用新服务可以,反过来则会崩溃。,实现类暴露多个接口,接口从另一个接口继承,实现类从多个接口继承,运行时类型识别,(RTTI),,,dynamic_cast.,功能升级扩展带来的问题接口的改变或增加都可能导致客户代码重新,接口继承,继承接口类定义:,class,IFastString2:,public,IFastString,public,:,virtual,int,FindN(,const char,*psz),const,=0;,运行时类型识别用法:,int,FindNth(IFastString*fs,int,n),IFastString2*fs2=,dynamic_cast,(fs);,if,(fs2)j,return,fs2-FindN(“very”,n);,else,error,(“,类型转换失败,不能进行查找,”);/,或者用别的实现,return,-1;,接口继承继承接口类定义:,接口继承,2,永久性支持,/,永久性对象,class,IPersistObject,public,:,virtual,void Delete()=0;,virtual,bool,Load(,const char,*,filename)=0;,virtual,bool,Save(,const char*,filename),=,0;,/,支持永久性的,Faststring,class,FastString:,public,IFastString,public,IPersistObject,private,:,int,m_cch;,char,*m_psz;,public,:,FastString(,const,char,*psz);,FastString(,void,);,void,Delete(,void,);,/,IFastString,的方法,int,Len
展开阅读全文