版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
COM第一个COM对象例子(G:\File\内部交流\赵国光\com\Example\DropTarget)IDropTarget的定义
interface
IDropTarget:public
IUnknown{
public:virtualHRESULTSTDMETHODCALLTYPEDragEnter(/*[unique][in]*/ IDataObject__RPC_FAR*pDataObj,/*[in]*/ DWORDgrfKeyState,/*[in]*/ POINTLpt,/*[out][in]*/ DWORD__RPC_FAR*pdwEffect)=0;
virtualHRESULTSTDMETHODCALLTYPEDragOver(/*[in]*/ DWORDgrfKeyState,/*[in]*/ POINTLpt,/*[out][in]*/ DWORD__RPC_FAR*pdwEffect)=0;
virtualHRESULTSTDMETHODCALLTYPEDragLeave(void)=0;
virtualHRESULTSTDMETHODCALLTYPEDrop(/*[unique][in]*/ IDataObject__RPC_FAR*pDataObj,/*[in]*/ DWORDgrfKeyState,/*[in]*/ POINTLpt,/*[out][in]*/ DWORD__RPC_FAR*pdwEffect)=0;
};什么是COMComponent
ObjectModel(组件对象模型)微软提出的二进制上的组件标准,定义了对象(组件)之间进行通信的协议。COM是一个更好的C++C++库厂商的麻烦某一个c++库厂商开发生产了一个算法,可以在O(1)时间阶内完成字符串搜索。为了让客户能够简单的使用这个算法,库厂商创建了一个类:FastString示例:faststring.hfaststring.cpp软件分发传统上,库厂商分发C++库一直以源码的形式进行.问题:代码复制,多个应用使用相同的代码占用磁盘空间以及内存.代码更新,将源码重新分发,重新编译链接,失去了模块化的特征.示意图应用A应用C应用BFastString.objFastString.objFastString.obj动态链接库(dll)为了解决重复代码以及更新困难的问题,将FastString类封装为一个dll是一个马上想到的方法._declspec(dllexport)关键字.引入库(import
library)示意图应用A应用C应用BFastString.dllDll引入库C++的可移植性C++缺少二进制级别的标准编译器和链接器的兼容性名字的问题,链接时表达符号名字为了支持函数重载和操作符重载,不同的编译器/链接器会任意修改入口点的符号名字,称为名字改编(name
mangling)使用extern
“C”可以消除名字改编现象,但只对全局函数有效.使用模块定义文件(Module
DefinitionFileDEF).在运行时表达语言的不同特征编译器厂商对语言的特征有不同方式的实现,异常(Exception)是一个例子.封装性的问题假如已经解决了编译器和链接器的问题,建立二进制组件的下一个障碍则和封装有关.FastString的Length方法有问题,修改FastString类的定义.FastString
dll升级为2.0,解决Length的问题.FastString
Dll分版本改名策略.新应用(用修改后的FastString)旧应用FastString.dll(2.0)接口与实现的分离封装的基础在C++中,这个原则没有应用到二进制层,因为C++类即是接口也是实现.如何做到接口与实现的分离将接口与实现分立成两个实体,在c++中表现为两个类,接口类和实现类.接口类只对一定的数据类型进行描述.实现类对数据类型作具体的实现.接口类的定义faststringitf.hclass
FastString;class
__declspec(dllexport)FastStringInf{
private:
FastString*m_pObj;
public:FastStringInf(const
char*psz);~FastStringInf();
intLength()const;
intFind(const
char*psz)const;};《示例:G:\File\内部交流\赵国光\com\Example\faststringdll2》使用面向对象的特性编译器/链接器的问题依然没有解决。利用所有编译器/链接器的一致性。复合结构在运行时表现形式对不同编译器一致.所有编译器使用相同的堆栈规则传递参数.所有C++编译器实现相同的虚函数调用机制.也就是说对每个c++编译器来说,一个对象在内存中如何表示,以及在运行时怎样调用虚函数都必须一致以上三条假设所有编译器必须要遵从.使用抽象基类作为二进制接口vptr以及vtbladjustorthunk(win32),CFRONT(solaris)vptrv_fun1v_fun2v_fun3vtblIFastString/接口FastString的抽象基类class
IFastString{public:virtual
intLength()const=0;virtual
intFind(const
char*psz)const=0;};vptrLengthFindvtblIFastString内存结构FastString/实现class
FastString
public:IFastString{private:
const
intm_cch;
char*m_psz;public: FastString(const
char*psz); ~FastString(void);
intLength(void)const;
intFind(const
char*psz)const;};vptrLengthFindvtblFastString内存结构m_cchm_psz唯一的全局函数extern“C”IFastString*CreateFastStringObject(constchar*psz){
returnnewFastString(psz);}new方法在dll内部被调用。析构函数的问题考虑如下用法:IFastString
*fs=CreateFastStringObject(“helloweveryone”);if(fs){ intpos=fs->Find(“very”); deletefs;}问题:内存泄露。原因:IFastString的析构函数并不是虚函数。解决办法:显示的使用删除方法删除自身。示例:G:\File\内部交流\赵国光\com\Example\faststringdll3动态载入dll的好处减少应用程序初始化的工作。dll不存在也不会导致系统出现错误。在运行时动态选择不同的实现。(另外的意义是组件升级)功能升级扩展带来的问题接口的改变或增加都可能导致客户代码重新编译。class
IFastString
{public:virtual
int
Delete(void)
=
0;virtual
intLength()const=0;virtual
intFind(const
char*psz)const=0;//新功能virtualintFindN(constchar*psz)const=0;}新方法追加在接口定义的尾部,老客户使用新服务可以,反过来则会崩溃。实现类暴露多个接口接口从另一个接口继承实现类从多个接口继承运行时类型识别(RTTI),dynamic_cast<>.接口继承继承接口类定义:classIFastString2:publicIFastString{public:
virtual
intFindN(constchar*psz)const=0;}运行时类型识别用法:int
FindNth(IFastString*fs,intn){ IFastString2*fs2=dynamic_cast<IFastString2*>(fs);
if(fs2)j
returnfs2->FindN(“very”,n);
else{
error(“类型转换失败,不能进行查找”);//或者用别的实现
return-1; }}接口继承2
–永久性支持//永久性对象classIPersistObject{public:
virtualvoidDelete()=0;
virtual
boolLoad(constchar*filename)=0;
virtual
bool
Save(constchar*
filename)
=
0;}//支持永久性的FaststringclassFastString:publicIFastString,publicIPersistObject{private:
intm_cch;char*m_psz;public: FastString(const
char*psz); ~FastString(void);
voidDelete(void);
//IFastString的方法
intLength(void)const;
intFind(const
char*psz)const;
//IPersistObject的方法
bool
Load(const
char*filename);
boolSave(const
char*filename);}boolSaveString(IFastString*fs,char*filename){IPersistObject*po=
dynamic_cast<IPersistObject*>(fs);
if(po)
returnpo->Save(filename);
else
returnfalse;}RTTI的问题RTTI是与编译器相关的特性,不同的变异其厂商对其有着不同的实现。这样就破坏了以抽象基类作为接口而获得的编译器独立性。解决方法:每个接口自己实现dynamic_cast的功能,这样仍然保持编译器独立性。修改后的接口类classIPersistObject{public:
virtual
void*Dynamic_Cast(const
char*type)
=0;
virtual
voidDelete()=0;
virtual
boolLoad(constchar*filename)=0;
virtual
boolSave(constchar*filename)=0;}classIFastString{public:
virtualvoid*Dynamic_Cast(const
char*type)
=0;
virtualvoidDelete()=0;
virtualintLength()=0;
virtualintFind(constchar*psz)=0;}//extractmethodclassIBaseObject{public:virtualvoid*Dynamic_Cast(const
char*type)
=0;virtualvoidDelete()=0;}实现Dynamic_Cast方法classFastString:publicIFastString,publicIPersistObject{//…};void*FastString:Dynamic_Cast(constchar*type){
if(strcmp(type,”IFastString”)==0)
return
static_cast<IFastString*>this;
elseif(strcmp(type,”IPersistObject”)==0)
returnstatic_cast<IPersistObject*>this;
elseif(strcmp(type,”IBastObject”)==0)
returnstatic_cast<IFastString*>this; //????? returnNULL;}转为IFastString的原因:多继承引起的二义性。消除多继承引起的二义性可以使用虚基类技术,但c++里虚基类同样是编译器相关的特性。资源管理voidf(void){ IFastString*pfs=0; IPersistObject*ppo=0; pfs=CreateFastString(“Helloeverybody.");
if(pfs){ ppo=(IPersistObject*)pfs->Dynamic_Cast("IPersistObject");
if(!ppo) pfs->Delete();
else{ ppo->Save("C:\\test.txt"); ppo->Delete(); } }}问题创建的对象是IFastString指针接收的,但却是用IPersistObject接口Delete,并且对象只能被释放一次。在此,由于他们都是指向的同一个对象,所以资源释放没问题,但是如果在复杂的代码中,包含多个接口,多个对象的时候,资源释放将变得非常复杂和不易控制。解决方法:将资源释放部分放到实现内部,每个对象自己控制自己的生命周期。Delete方法的改造//基类抽象接口class
IBaseObject{
virtual
void*Dynamic_Cast(const
char*type); //virtual
void
Delete(void);
virtualvoidAddPointer();
virtualvoidDelPointer();};//实现实现类维护一个变量,在指针复制的时候增加,指针不用的时候减少,减至0时将对象销毁。class
FastString:publicIFastString,publicIPersistObject{
intm_pcount;public:
voidAddPointer(){ m_pcount++; }
voidDelPointer(){ if(--m_pcount==0) deletethis; }}接下来需要修改管理指针的接口,在指针被复制的时候调用AddPointer.对FastString
Dll来说,有两个地方需要修改,一是创建对象接口CreateFastStringObject,一是运行时动态类型转换接口Dynamic_Castvoid*FastString:Dynamic_Cast(constchar*type){ void*obj=NULL;
if(strcmp(type,”IFastString”)==0) obj=static_cast<IFastString*>this;
elseif(strcmp(type,”IP
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 门窗安装工程合同
- 科教年度工作计划模板7篇
- 体育馆门头房租赁合同
- 化肥公司医师聘用合同
- 学校建设电梯司机劳务协议
- 旅游度假鱼塘施工合同范本
- 临时司机招聘协议零时工
- 城市化妆品运输安全管理办法
- 个体玩具店店长聘用合同
- 汽车销售中介佣金协议
- GB/T 17892-2024优质小麦
- 调酒初级基础理论知识单选题100道及答案解析
- 危废治理项目经验-危废治理案例分析
- 南京市2024-2025学年六年级上学期11月期中调研数学试卷二(有答案)
- 汽车防冻液中毒
- 粉条产品购销合同模板
- 2024至2030年中国自动车配件行业投资前景及策略咨询研究报告
- 2024-2030年中国蔗糖行业市场深度调研及发展趋势与投资前景研究报告
- 北师版 七上 数学 第四章 基本平面图形《角-第2课时 角的大小比较》课件
- 外研版小学英语(三起点)六年级上册期末测试题及答案(共3套)
- 北师大版(2024新版)七年级上册生物期中学情调研测试卷(含答案)
评论
0/150
提交评论