入门-5.组件技术手记_第1页
入门-5.组件技术手记_第2页
入门-5.组件技术手记_第3页
入门-5.组件技术手记_第4页
入门-5.组件技术手记_第5页
已阅读5页,还剩395页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

关于本课软件技术的发当前软件状COM和CORBA简本课程的内课程安关于本课展 软件技提高软件设计能软件领域的发软件需求的变软件环境的变程序设计方法的发功能分解法——计算任 结构化程序设计——以数据为中 面向对象程序设以对象为中心组件程序设计——以组件为中 软件需求的变实管理软件环境的变 多多任图形界多线平台相

单一语网络(分布式)软件开发模

OS+Compiler+

OS+Compilers++Libraries+++other经发展变化的结不变因素回顾软件学科10多年来的变 —混软件的分发过程软件工程对象技用一种新的思路来看待问三大特性:封装性、继承性、多态Object-Object-组件技组件技术适合于现代的软件环组件可独立发布要求“接口与实现分离组件infrastructure,组件体COM、CORBA(和中间件(middleware)市国内的状问题 C++之必要性 类是定义,它封装了状态和操对象是实例,它反映了具体的事对象由类来定概念:组定义:可独立发布的二进制单有的地方称作容 例如概念:reuse(重用、复用不同形式的不同层次的例子概念:接口与实现分Interfaceand对象技术和组件技术都强接口是对象或者组件的通信协实现是对象或者组件的内部细接口的发概念去是软件设计的重 ,也是目不同层次上的对象技术中的重要概以一致的方式来看待不同的事在C++中,通过继承和虚成员函数来实运行时刻绑定:runtime在组件技术中,通过接口来体概念模不同层次上有不同的定有些操作与模块相:模板函数模板和类模抽象层次更泛型技术(generic已纳入C++标准之例子这是指软件的结C/S是基多层结构具有较好的灵活性和可扩展多层结构与基于组件的系统相结变种概念:其防 概软件形单机软Client/Server软分布式软 软件的复杂度增软件升级和更分布式软件的发布和配软件发 的问题(续Custom-madeversusstandard依赖于全才开发人软件的可扩展 如Web——〉发展组件软件、软件组软件基础设施的重要API的多样软件方案(solution),consulting市组件软部分升增加了异构软件的可 动态组合,提高软件生产符合现代软件的发展要软件组关键:接口设对基础设施的依内部独立设计、独立开独立发布、独立测COM(ComponentObjectCORBA(CommonObjectRequestBrokerCOM:组件对象模建立在二进制层次上的标COM规COM实COM特语言无 进程透明——〉位置透inprocserver、out-of-proc多线程特可扩展COM:接COM接口特性COMCOM对象特性COM:组进程内组Export进程外组COM:进程内组Inproc–Export客客 组COM:进程外组Out-of-proc客客运行提供DCE(客户进程

组运行组提供DCE(组件进程(组件进程 组remote

DCEDCEDCECOM:组件信息发表工具和配置工 MTSExplorerCOM:创建COM对COMCOMCOM:COM对象管COM实现优组件类component COM:COM体扩展功COM:应ActiveX功能扩OLE其COM:分布式应 OLE集成Active CORBA规CORBA实现CORBA体系结CORBA:跨平台、跨语多种平CORBA客ORB进行通CORBA:对编写IDLIDL-〉利用生成的stub类编写客利用生成的impl类编写服务器对CORBA字符串形式的GIOP(GeneralInter-ORBIIOP(InternetInter-ORB实现仓库、接口仓CORBA:服命名服Trading事件服课程内容(一准备知课程内容(二 课程内容(三CORBA介中间插1-2次新技术报考核办作考参考书《COM本质论《COM原理与应用《COM技 DesignPattern》或者《设计模式AdvancedCORBAProgrammingwithC++C++语言基 内容简C++语言基C++之我掌握C++语言的基础知操作系统的基础知 计算机原编译和执行过许多概过过程

No结果正确? BuildmieCompile+如何对待错误和警学会设置compileoptions和link

执行过程Load、重定位、初始化、如何调程序对环境的依赖C语言例voidmain(void{/*STRCPY.C:Thisprogramuses*andstrcattobuilda#include#include

charstrcpy(string," oworldfrom");strcat(string,"strcpy");strcat(string,"and");strcat(string,"strcat!");printf("String=%s\n",string}C语言特结构简单的方法可以构造复杂的结表达式灵活、简提供了一些接近汇编语言的功能及指适合于编写系统软件和工具软件;指针非常灵调试方移植性目标代码小、效率C++语言内数据类表达控制语函数(模板异常处常

数据类true、’a’、”filenameis变基本数据类void、charshortintlong、float、double、、指

数据类型(续一 字符const修饰类数据类型(续二 const定义常constintsize100;在size的有效范围内不可char*constaptrmybuf;*aptr=aptr=

合constchar*bptrmybuf;指向常量数*bptr=‘a’;bptr=yourbuf;

合constchar*constp=char*p 合法,例const也可以用在函数的参数说明在类的定义中intGetData( //不会改变对象的数数一维数intnumber[100];externintnumber[];数intnumber[100][10];externintnumber[][10];结构数structfloatx,}结构简单结struct{intyear,month,day;charmon[3];

结构和嵌套结structphone{intareacode;longnumber; structphone; 结}Jim.number 结构struct(续结构中的位struct{unsigneda:4;unsignedb:5;unsignedc:7;}结构中的成.操作Jim.number 联合联合类union{intival;floatfval;char*pval;MFC中典型的例子是VARIANT的定联合与结构的区内存分配 方enum{枚举sunday=0,枚举型型}

缺省saturday指定sunday//monday=//tuesday=定义变量today为类型enumDaysyesterday;Daystomorrow;yesterday=monday;inti=tuesday;yesterday=0;yesterday=(Days)0;

C和C++C++合法i 例typedefcharFlagType;constFlagTypex;typedefint(FARWINAPI*FARPROC)();typedefint(WINAPI*PROC)();PROCintretVal=自定义变量的说

无名联合、结例如structfruit{ char*name;union{DWORDcolor;struct{BYTEred;BYTEgreen;enumEnumDayday;structStructPointpoint;unionUnionColor

---------EnumDay---------StructPoint---------UnionColor

BYTE 指 intx,*px;px=&x;

pn表示紧接*p之后的第npn表示紧靠*p之前的第np1p2int**ppx表示指向int*

structdate 注意对pd一定要赋相当

&x表示取x的地*px表示取px所指的变object.*pMember表 对象object的指针成pMenmber所指的变pobject->*pMember表 pobject所指对象的针成员pMenmber所指的变指针的转换有很大的随意性,但一定要保证安全

intx,*pa;pa=x=若有以下说struct{intx,*y}p-(++p)-*p-*(p-*p++-*(p++)-

x加 // y的内容,再加同// y的内容,后p加// y的内容,后p加定义:void(PASCAL*pFunc)(int,赋值:pFunc调用:(*pFunc)(100,——int&r=指针变#include<stdio.h>voidswap(int*a,int*b){inttmp=*b=*a=tmp;}int{inti=7,j=3;swap(&i,&j);printf(“TheResultis:i=%d,““j=\n”,i,j);return}

#include<stdio.h>voidswap(int&a,int&b){inttmp=b;b=a;a=tmp;}int{inti=7,j=3;swap(i,j);printf(“TheResultis:i=%d,““j=\n”,i,j);return}变量类

例如,在某个函数内部:autoint明:externint例如:staticint例如:registerintregistercharstaticinti**/externintTotal;intAdd(intx,inty){intz;/*externintTotal;*z=x+y;Total++;returnz;}intSub(intx,int{intz;/**/staticintSubTime0;z=x-y;returnz;}

变量类型例intTotal=intmain(){registerinti1,i2;/**/intResult1,Result2;i1=i2=Result1=Add(i1,i2);Result2=Sub(i1,printf(“i1=%d,i2=%d\n”,i1,i2);printf(“Result1=%d,Result2=%d\n”,Result1,Result2);return0;}new和分配内在Cchar*name=(char*)malloc(Length+char*name=newchar[Length+释放内在C使用delete[]表达算术运算 -++-关系运算! 赋值运算=条件运算sizeof运算

!= 表达式(续New、按位运算、求反运 ^、~(求反移位运 逗类型转复合表达控制语if、return、表达式、for、continue、break、while、do-try、复合语逗号既可作分隔符,也可作运算空操作语控制语句例if条件表达式if条件表达式)语句Aelse语句B把一组语句用if条件表达式)语句}表达式1表达式2表达式

switch(表达式) case表达式1:语}控制语句例子(续–while(表达式 语for(表达式 表达式赋初值结束条件dowhile表达式

boolFunc(intx,int说明:voidfunc(inta,intbint定义:调用 相当于返回

函数(续一引出函数inlinevoidfunc(inta,int{printf(“%\na=%d,b=%d\n”,a,}extern函数(续二命令行参数:intargccharextern调用参数处理 参数不确例如:intprintf(char*,函数指针定义函数指针函数(续三比如:#includeusingnamespace#includevoidprint(inti);voidprint(char*s);voidprint(int*p);void{函数例/*Functiondefinition*/voidwork(intnumber,long(*function)(inti){int longfor(i=j=0;i<number;i++)j+=(*function)(i);}

/*Functionprototypeslonglift(int),step(int),drop(int);voidwork(intnumber,long(*function)(inti));intselect, select=switch(select case1:work(count,lift);case2:work(count,step);case3:work(count,drop}}说明

变量说externintexternintglobal 定义函数说voidFunc(intx,int*隐含说*通常#include文件中包含的是函数的说struct{intx;int定

定变量定int函数定voidFunc(intx,inty)}

structPOINT{intx;intstructPOINT作用

local{}namespacenamespaceXXX}classscopeoperatorusingnamespace函数重

不能包含两个extern重载版重载函数指函数模

例子template<classType>Typemin(Typea,Typeb){return}min(10.0,20.0);模板实例化——由参数决函数模板(续两种编译模模板特重载函数模异常处理(exception错误处理机制、错误代Throw(raise)anThrowTry、catch语句catch(type){}catch(type异常处理(续terminate来处Localobject正常析Catchall函数时指定函数可能的异intfunc(int)

预处理及其格式:#define符号名例如:#defineTRUE1

#define y%4==0&&y%100!=0#defineIS_LEAP_YEAR(y) 预处理及其他(续#ifdef

或者#ifndef标识 或者

#ifdef \n \’ \xhhh对构造函数与析构函控制、友嵌套类中成员初始虚拟函类模类的定class{privateprotectedpublic

类的例class{COLORREFcolor;CShape(){color=0;}virtual~CShape(){}virtualvoidDisplay()=virtualvoidMoveTo(intx,inty)=构造函

构造函数和析构函构造函Copy构造函构造函数与析构函数示CPoint*point1=newclassCPoint:public{privatePOINTCPoint(constCPoint&);CPoint(intx,inty);voidSetPoint(POINT);voidDisplay();voidMoveTo(intx,int

deleteCPoint*point2=newCPoint(100,delete{CPointCPoint 类的实

CPoint::CPoint(intx,int{m_point.x=x;m_point.y=}{}voidCPoint::SetPoint(POINT{m_point=}void{}voidCPoint::MoveTo(intx,int{m_point.x=x;m_point.y=}的classCPointintx,y;staticint…staticintintCPoint::nCount=intCPoint::GetCount(){returnnCount; 指向类成员的指例如:classCShape{intx,intwidth,…intintintpf=CShape::GetHeight;

////运算符重

!,

>> [(deletenew[]比如operator=返 类型:return例双目运算符说明CComplexoperator+(CComplexcomplex)定义CComplexCComplex::operator+(CComplexcomplex){returnCComplex(x+complex.x,y+}使用Complexz1,z2,……初始z1和z2z3=z1+z2;单目运算OperatorclassCPoint{operatorchar*();char*point=static_cast<char类指CComplexp=newCComplex(1,CComplexz1(10,10);p=&z1;

this指类成员 问特三种特友

classclass{intintgood();IOErrorclass{int{}int{}classBufferIO{public:enumIOError{none,General友class{Complex(floatre,floatim);friendComplexoperator+(Complexfirst,Complexsecondfloatreal,Complexoperator+(ComplexComplexsecond{returnfirst.real+second.real,first.imag+second.imag);}

class{friendclass//Declareafriendclassintclass{voidchange(MyClassmycvoidMyClassmyc{//可 } 板板 template<classT>class{template<classT>T&a,{Ttemp;temp=a;a=b=}

privateTpool[maxNum];intsp;voidPush(Tx);TPop();BOOLIsEmpty()BOOLIsFull()Stack<int>intStack;Stack<float>floatStack;模板(续inclusion模separation模式(export关键字partialspecializations)从面向过程转换到面向对通过数据结构来描述具体的问题数据在功能(函数)之间以参数的形式被传送面向对多态性Object-Oriented类的继继继承生派生类特

派生classderived_class_name:private{…classderived_class_name:public{… int int int int charclass int intpublicparent charch; intnew1;classpublicinta;charch;intnew1;intintmethod1();intmethod2();intmethod3();(续二

//利用父类的构造函数进行初始derived::derived(intInit_a,charInit_ch,int:parent(Init_a,{new1=}:1基2内嵌对派生

derived2::derived2(intInit_a,charInit_ch,intInit_new1,intInit_new2):derived(Init_a,Init_ch,{new2=}(续三

CShape*obj=newdelete如果不定义成virtual,则memory派生类类(续四)——多(续五

该调用特定的函数,则必须冒号MyDerivedClass*p=new数多态性和虚拟拟数virtualvoid调用CShape*pShape=GetCurrentShape();纯虚函定义:virtualvoidDisplay0404classAprivateintvalue;virtualvoidvirtualvoid

048对象的内存048classB:pulicA{private:intvalue1;virtualvoidvirtualvoid

048对象的内存048classB:pulicA{private:intvalue1;virtualvoid

classC{privateclassC{private:intvalue2;virtualvoidFunc3(void)virtualvoidclassD:publicC{private:intvirtualvoidclassE:publicB,publicD{private:intvalue4;virtualvoidFunc1(void)virtualvoidCACAEEDB048继承关虚基类的构造由themostderived类型转voidDraw(CShape{//shape-//shape-if(dynamic_cast<CRect*>(shape))}C++标准iostreamostream&operator<<(ostream&os,constMyClass)istream&operator>>(istream&os,STL(StandardTemplateGenericSTLSTL数据类算 容STL容关联容器(AssociativeSTL迭代 STL改变顺序的操不改变顺序的操排序及相关操常用的数字操使用#include<functional>#include<list>#include<iostream>#include<algorithm>usingnamespacestd;template<typenameT>voidprint_elements(T{cout<<elem<<"";void(*pfi)(int)=

void{intia[7]=list<int>ilist(ia,listfor_each(ilist.begin(),ilist.end(),//012345for_each(ilist.begin(),ilist.end(),pfi);//0123456707ilist.remove_if(bind2nd(modulus<int>(),for_each(ilist.begin(),ilist.end(),//0246}C++参考“DesignandEvolutionofC++”“C++ProgrammingLanguage”“C++Primer”(3/e)“InsidetheC++ObjectModel”“EffectiveC++”(2/e)“MoreEffectiveC++”“ExceptionalC++”“C++StrategiesandTactics”“GenericProgrammingandtheSTL” 组件的接COM接COMCOM对从历史看OLE1COM又从OLE中脱颖而 COM基础——几个概COM对如何设计COM对 设计COM——从C++class{char*m_psz;CMyString(constchar*constchar*Find(constchar*psz);intLength();设计COM——从C++入手(续:m_psz(newchar[psz?strlen(psz)+1:1]){if(psz)m_psz[0]=}delete[]m_psz;}constchar*CMyString::Find(constchar*psz){returnstrstr(m_psz,psz);}intCMyString::Length(){returnstrlen(m_psz);}C++类 静静 的缺 C++类 linking(续#ifdef#defineEXPORTORIMPORT动动 形

classEXPORTORIMPORT{CMyString(constchar*constchar*Find(constchar*psz);intLength();接口如 接 C++中类形式的接口存在的问若用VisualC++5.0/6.0客户眼中的C++类(续如果是BorlandC++编译器(4.02)命 解决方案命 解决方案模块定义文件(.def)中给出序号别LIBRARYMYSTRING LIBRARYMYSTRING 命 解决方案C++类的vtable不随编译器而变vtable要求这些接口函数必须是虚函客户如何得到C++对象的二进制结new/delete是编译器相关C++对象的二进制结构是编译器相关C++对象与客户之间的连接问方案1:句句柄方class{char*m_psz;CMyString(constchar*constchar*Find(constchar*psz);intLength();

classCMyString;classEXPORTORIMPORT{IMyString(constchar*constchar*Find(constchar*psz);intLength();案前提条件048虚函数048classB:pulicA{private:intvalue1;virtualvoidvirtualvoid

纯虚基类方44{virtualconstchar*Find(constchar*psz)=0;virtualintLength()=0;

纯虚接口的使用 #include客户怎么使用

classCMyString:public{CMyString(constchar*constchar*Find(constcharint如何创建对DLL的唯一接口是引出函extern"C"_declspec(dllexport)IString*CreateString(constcharextern"C"IString*CreateString(constchar{returnnew}通过引出函数创建对extern"C"IString*CreateString(constcharvoidmain(){IString*p;p=CreateString(" if(p){constchar*psz=p->Find("llo");intn=p->Length();}#includevoidmain(){IString*p;HANDLEh=创if(NULL!=h)创PfnCreateStringpfn if(pfn)对p= 对if(p)constchar*psz=p-象intn=p-象}}//Becarefulaboutcalling}如何删删删除后,所以比较好但是不能用可以让对象自己把自己删在IString中增加一个方class{virtualvoidvirtualconstchar*Find(constchar*psz)=0;virtualintLength()=0;classCMyString:public{char#includevoidmain(){IString*p;p=CreateString(" if(p){constchar*psz=p-intn=p->Length();}

CMyString(constchar*psz);virtual~CMyString();voidconstchar*Find(constchar*psz);intLength();voidCMyString::Delete(){deletethis;}小更高的要求对象的进在原有接口的基础上增加新的功能,例class{virtualvoidvirtualconstchar*Find(constchar*psz);virtualintLength();virtualcharFindAt(int对象的进化(续完全增加新的功class{virtualvoidvirtualvoidSave(constchar*pszFile);virtualvoidLoad(constchar*pszFile);?接口的进对象的接口不能发生变classIString2:public{virtualcharFindAt(int新对象实现两个接口:IString2和 对象实现多个接atruntime,客户可以灵活地从一个接口变换回忆RTTI(Runtimetype对象实现多个接口(续一——robust对象实现多个接口(续二class{virtualvoidvirtualvoid*Dynamic_cast(constchar*psz)=0;virtualconstchar*Find(constchar*psz)=0;virtualintLength()=0;classIString2:public{virtualcharFindAt(int对象实现多个接口(续三classCMyString:publicvoid*CMyString::Dynamic_cast(constchar{ifreturnstatic_cast<IString*>(this);ifreturnstatic_cast<IString2*>(this);returnNULL;}对象实现多个接口(续四#includevoidmain()IString*p=CreateString(" if(p){IString2constchar*psz=p->Find("llo");intn=p->Length();charc=p2->FindAt(3);}对象实现多个接口(续五class{virtualvoidvirtualvoid*Dynamic_cast(constchar*psz)=0;virtualvoidSave(constchar*pszFile)=0;virtualvoidLoad(constchar*pszFile)=0;对象实现多个接口(续六#includeclassCMyString:publicIString2,publicIPersistvoid*CMyString::Dynamic_cast(constchar*psz){if(strcmp(psz,"IString")==0)returnstatic_cast<IStringifreturnstatic_cast<IString2*>(this);ifreturnstatic_cast<IPersist*>(this);returnNULL;}对象实现多个接口(续七voidmain()IString*p=CreateString(" if(p){IString2*p2;IPersist*p3;constchar*psz=p->Find("llo");intn=p->Length();charc=p2->FindAt(3);}数 对象的生命周期管客户可能拥有多个指向对象的,每个各有自己的lifetime outstandingreference未完结 对象的生命周期管理(续 记录当前outstandingreference的数目。户时为1,以后由客户管理,当计数当客户通过获得新的接口指针时,引计数的两个操我们用计数

class{virtualvoidvirtualvoid*Dynamic_cast(constchar*psz)=0;virtualvoidDuplicatePointer()=0;virtualconstchar*Find(constchar*psz)=0;virtualintLength()=0;class{virtualvoidvirtualvoid*Dynamic_cast(constchar*psz)=0;virtualvoidDuplicatePointer()=0;virtualvoidSave(constchar*pszFile)=0;virtualvoidLoad(constchar*pszFile)=0;#include

classCMyString:publicpublic{charCMyString(constchar*voidDestroyPointer();void*Dynamic_cast(constchar*);constchar*Find(constchar*psz);intLength();charFindAt(intvoidSave(constcharvoidLoad(constchar

:m_psz(newchar[psz?strlen(psz)+1:1]),m_refcount(0){if(psz)m_psz[0]=}if(0<m_refcount)m_refcount--deletethis;}}制void*CMyString::Dynamic_cast(constchar*psz)制void*p=ifp=static_cast<IString*>(this);ifp=static_cast<IString2*>(this);ifp=static_cast<IPersist*>(this);if(NULL!=p)returnp;}voidmain()IString*p=CreateString(" if(p){IPersist*p3;constchar*psz=p->Find("llo");intn=p->Length();charc=p2->FindAt(3);p2-}p3-}p-}修改创建函让创建函数也正确 计extern"C"void*CreateString(constcharconstchar{void*pret=CMyString*p=newCMyString(psz);if(NULL!=p){if(NULL==pret)delete}return接口整每个接口都需要下面的三个函class{virtualvoid*DynamicCast(constchar*psz)=0;virtualvoidDuplicatePointer()=0;virtualvoidDll什么时候被卸载如何标识一个接口?字符串线程安全如何标识一个对象?对象 跨进程?跨机器?对象环境COM接接口标识——COM接口二进制结COM接口的标识——typedefstruct_GUIDextern"C"constGUIDCLSID_MYSPELLCHECKER{0x54bf6567,0x1007,}{0xb0,0xaa,0x44,0x45,0x54,0x00,0x00}}IUnknown接所有的COM接口都从IUnknown派C++定义class{virtual stdcallconstIID&iid,void**ppv)=0virtualULONGvirtual

stdcallAddRef()=0;stdcallRelease()=0;IUnknown接口(续C定义typedefstruct{HRESULT( RPC_FAR*

RPC_FAR*QueryInterface/*[in]*/REFIID/*[iidis][out]*/voidRPC_FAR* ULONG(STDMETHODCALLTYPE_RPC_FAR*AddRef)( RPC_FAR*ULONG(STDMETHODCALLTYPERPC_FAR*ReleaseIUnknownRPC_FAR*}interface{CONST_VTBLstructIUnknownVtblRPC_FAR对象实对象实C语言描述示例——structstruct{IDictionaryVtbl*struct{/*…QueryInterface,AddRef,Release*/BOOL(*Initialize)(IDictionary*this);BOOL(*LoadLibrary)(IDictionary*this,BOOL(*InsertWord)(IDictionary*this,String,String);void(*DeleteWord)(IDictionary*this,String);BOOL(*LookupWord)(IDictionary*this,String,String*);BOOL(*RestoreLibrary)(IDictionary*this,String);void(*FreeLibrary)(IDictionary*C++语言描述示例—classIDictionary:public{virtualBOOLInitialize()=virtualBOOLLoadLibrary(String)=0;virtualBOOLInsertWord(String,String)=0;virtualvoidDeleteWord(String)=0;virtualBOOLLookupWord(String,String*)=0;virtualBOOLRestoreLibrary(String)=0;virtualvoidFreeLibrary()=ULONGRelease();voidFreeLibrary(this*);CDictionaryCOMCDictionaryCOM接口的内存模型(续一CDictionary类中COM接口的内存模型(续二CDictionary类中虚函数的具体实另一个字典对象类中虚函数的具21接口查的途径函数QueryInterface(iid用法返回值说明了对象对接口的支持情接口查询用法示//loadtheretValue=pIDictionary->LoadLibrary("eng_ch.dict");if(retValue==FALSE) ISpellCheck*pISpellCheck;HRESULTresult(void**)&pISpellCheck);if(result!={pIDictionary->Release();return;//......useinterface//finally,releasedictionaryobjectpISpellCheck->Release(QueryInterface实与对象的定义有QueryInterface实现举classCDictionary:publicIDictionary,public{publicpublic://IUnknownmember virtualHRESULTQueryInterface(constIID&iid, virtualULONGvirtualprivateintm_Ref

AddRef();Release()thisthis成员函IDictionaryIDictionaryvtable指ISpellCheckvtable指的属性数HRESULTCDictionary::QueryInterface(constIID&void{if(iid==IID_IUnknown)*ppv=static_cast<IDictionary*>this;((IDictionary*)(*ppv))->AddRef();}elseif(iid==IID_Dictionary)*ppv=static_cast<IDictionary*>this;((IDictionary*)(*ppv))->AddRef();}elseif(iid==IID_SpellCheck)*ppv=static_cast<ISpellCheck*>this;((ISpellCheck*)(*ppv))->AddRef();}else*ppv=returnE_NOINTERFACE}return}COM对象的接口原IUnknown接口一致接口对称接口自反接口传递接口查询时间无关计目的:是为了控制对象的生命周多个客户可以独立地控制对象的生计数反映了被客 的个–Outstanding两个操作:增一和减 实 计组件模 组 计数对象对 计

对 计数接 计

接 计

接 计

接 计实 计数三种方组件对象计数实现示classCDictionary:public{publicpublicQueryInterface(constIID&void**ppv)AddRef()Release()virtualBOOLInitialize();virtualBOOLLoadLibrary(String);//privatestructDictWord*m_pData;char*m_DictFilename[128];intm_Ref;计数实现示例(续CDictionary::CDictionary{m_Ref=//...}ULONGCDictionary::AddRef{m_Refreturn(ULONG)}ULONGCDictionary::Release{m_Ref--return(ULONG)}计数用客户 接口时——增一操客户用完接口时——减一操当对象 计数为0时,释当组件中所有对象 计数为0时,卸AddRef和Release的返回值不可计数使用用示//loadthe示if(retValue==FALSE){}IDictionary*pIDictionaryForWord=pIDictionary;pIDictionaryForWord->AddRef();//InsertordeletesomewordpIDictionaryForWord->DeleteWord("...");pIDictionaryForWord->Release();//finally,releasedictionarypIDictionary->Release( 局部接口指针变类成员变使 计数数规则(一般性规优计数问计数实现举ULONGCDictionary::AddRef{m_Refreturn(ULONG)}ULONGCDictionary::Release{m_Ref--if(m_Ref==0{deletethis;return0;}return(ULONG)}总结:COM接口特接口不变继承性(扩展性接口描述语言interfaceIDictionary:{HRESULTHRESULTLoadLibrary([in]HRESULTInsertWord([in]string,[in]string);HRESULTDeleteWord([in]string);HRESULTLookupWord([in]string,[out]string*);HRESULTRestoreLibrary([in]string);HRESULTIDL简基本数据类IUnknown接口的IDL描[local, ]interface{typedef[unique]IUnknown*LPUNKNOWN;HRESULTQueryInterface([in]REFIIDriid,[out,iid_is(riid)]void**ppvObject);ULONGAddRef();ULONG}IDL中类的描[helpstring("Aclass"),helpcontext(2481),appobject]coclass{[source]interfaceIMydocfuncs:IUnknown;dispinterfaceDMydocfuncs;IDL中库的描[ o2.0TypeLibrary"),] {/*LibrarydefinitionstatementsIDL中library示[object,uuid(...),<other]interfaceIKnown:{import<declarations,etc.forIKnowninterfacegohere>[<library]

library{//referenceinterfaceinterface//orcreateanewclass:<coclass]coclass{interfaceIDL的意MIDL.exe产生C++头文件定MIDL.exe产生TLB类型描COM对包括属性和方法,或者状态和操能够提供服务——通过COM接COM对象的标识——创建对象的时候必须要提供COM对象封装特可重用COM对象和接口图今天讲讲讲课内容的参“COM原理及应用”第二“COM技 ”前四“COM本质论”第一、二“COM

自由作读程 表组件接第一个里程 第二个里程 COM接接口标class{virtual stdcallconstIID&iid,void**ppv)=0virtual stdcallAddRef()=virtual stdcallRelease()=对象实COM对象实COM 计计数的含Outstanding对象实 计客户显式 计 计数规COM接口 stdcallconstIID&iid,void一个COM对象可以实现多个接QueryInterface实 客户通过QueryInterface使用对象的接编译器:MIDL.exe产生C++头文件定MIDL.exe产生TLB类型xxx_p.cxxx_p.cxxx_i.cxxx.hC++COM对封装:属性和方法,或者状态和操对象与接口的联实现形进程内组inprocess进程外组outofprocess进程内组客户:用到的API函数,LoadLibrary说明进程外组DLL(DLL(①应用APIDLLLPC调用服务③服务f通过LPC返回结进程外组件(续⑥对象返①客户调用接口成

中中

②代理对象通DLLLPC

连接回顾:对象与与客户户之间连接客户如何获得第一个接口指如何创建(create)?激活客户如 这个函数创建函方案创建函数(续该对象被称为类对象,也称为类现在问题是:如何创建类厂对客户-〉引出函数-〉类厂对象-〉用户对引出函数的名字固增加了一层间接性,带来灵活}

类厂:用于创 对象 对 特殊性类厂(续字字典组类字典对多对象、多类厂组类厂对象创建类厂对llGetClassObject创建类厂对DllGetClassObjectHRESULTconstCLSID&clsid,constIID&iid,(void**)ppv创建函数哪信结果接口指IClassFactory接classIClassFactory:public{virtual stdcallconstIID&iid,void**ppv)=virtual stdcallBOOLbLock)=提供信息过程创建过程的位置透透位置透明性可以极大地方便客户程如何做到位置透明解决方案COM方在Windows平台上,使用系统表保在客户与组件之间插入COM库,由库完成创建的细节工Windows系 树状结根是“My KEY_CLASSES_ROOT\CLSIDTreeView组件 信TreeView{6B7E6392-850A-101B- 回顾:COM对象的标例如{72d3edc2-a4c4-11d0-8533-ProgID:友好名,字符串形 TreeControl的ProgID信表其 工具RegEdit.exe、Regedt32、程 途径:Win32ComponentCategories(组件类别组件类COM组件进程内组例如:RegSvr32 RegSvr32/u 进程外组COM创建过 调用过COM建过类厂对象接口指COM创建一个类constCLSID&clsid,DWORDdwClsContext,COSERVERINFO*pServerInfo,constIID&iid,(voidHRESULTCoCreateInstance(constCLSID&clsid,DWORDdwClsContext,constIID&iid,(voidCoCreateInstance实现伪HRESULTCoCreateInstance(constCLSID&clsid,IUnknown*pUnknownOuter,DWORDdwClsContext,constIID&iid,void*ppv){IClassFactory*pCF; hr=CoGetClassObject(clsid,dwClsContext,NULL,IID_IClassFactory,(void*)pCF);ifreturnhr=pCF->CreateInstance(pUnkOuter,iid,(void*)ppv);return}HRESULTCoCreateInstanceEx(constCLSID&clsid,DWORDdwClsContext,COSERVERINFO*pServerInfo,DWORDdwCount,MULTI_QI个创建函数选用原 创建过程示意COM对组COM对组件程调用调用COM⑥

⑩⑦⑨②③⑤

⑧④classCDictionaryFactory:public{类 类厂CDictionaryFactory厂~CDictionaryFactory 实HRESULTQueryInterface(constIID&iid,void**ppv);ULONGAddRef();实 ULONG//IClassFactoryHRESULTCreateInstance(IUnknown*,constIID&iid,void**ppv)HRESULTLockServer(BOOL);CreateInstanceHRESULT*pUnknownOuter,constIID&iid,void{CDictionary*pObj;HRESULThr;if(pUnknownOuter!=returnpObj=newif(pObj==NULL)return//Obtainthefirstinterfacepointer(whichdoesanhr=pObj->QueryInterface(iid,if(hr!={g_DictionaryNumber--;deletepObj;}return}DllGetClassObject的实extern"C"HRESULTstdcallDllGetClassObject(constCLSID&clsid,constIID&iid,void**ppv){if(clsid==CLSID_Dictionary)CDictionaryFactory*pFactory=newif(pFactory== returnE_OUTOFMEMORY}HRESULTresult=pFactory->QueryInterface(iid,return}elsereturn}} IClassFactory::LockServer函COMCOM库的内存管组件程序的装载和卸COM用于创建过程的SCM(ServiceControl其COM成(续(COMclient)(COMserver)ServiceServiceControlManagerCOM库的初始基本的初始化函数HRESULTCoInitialize(void 初始化之前唯一可以调用的函数DWORD另一个初始化函数COM库的终止函数void IsEqualGUID、IsEqualIID、CLSIDFromProgID、StringFromCLSID、StringFromIID、类COM存管HRESULTCoGetMalloc(DWORDdwMemContext,IMallocclassIMalloc:public{void*void*

Alloc(ULONGcb)=Realloc(void*pv,ULONGcb)=0;Free(void*pv)=0;GetSize(void*pv)=0;DidAlloc(void*pv)=0;HeapMinimize()=0;COM库内存管理用法(一 length=MAX_LENGTH;IMalloc*pIMalloc; if(hr!=S_OK)//returnif//returnpszText=COM库内存管理用法(二三个封装函数void*CoTaskMemAlloc(ULONGcb);voidCoTaskMemFree(void*pv);voidCoTaskMemRealloc(void*pv,ULONGCOM库内存管理用法(三 length=MAX_LENGTH;IMalloc*pIMalloc; psz=CoTaskMemAlloc(length);if(NULL==psz)//returnpszText=COM库内管理用法(四WCHAR*pwProgID;charpszProgID[128];hResult=if(hResult!=S_OK) }wcstombs(pszProgID,pwProgID,128);载进程内组件的装载–进程外组件的装进程内组件的卸进程外组件的卸进程内组件客户调用COM库函数COM库调用DLL组件的引出函HRESULTCOM库中一些些常用数

COMCOM库的版本号COM库的初始化COM库功能服务终止GUIDGUIDIIDCLSIDCLSID结构形式把CLSID结构形式转化为字符串形式IID转化为IID结构形式把IID结构形式转化为字符串形式GUIDCOM创建COM对象,可指定多个接口或对COM对象创建函内存管理函HRESULT数据结 0类别码:反映了函数调用结果的基本情操作操作#define8#define3#define1#define9#define7#define#define0#define#define4#define2#define类别Win32SDK的头文件HRESULT(续FormatMessage函SUCCEEDED和FAILED常0。QueryInterfaceCOM进程外组件与客户的协作过定义必要的CLSID和IID实现COM对 实现类厂对 实现DllGetClassObject、(可选)实现两 函进程内组件与客户的协作过COM组件程序CLSIDclsidIClassFactory*pClf;IUnknown*pUnknown;"Dictionary.Object",NULL,(void

COM 表中查找字典COM库在内存中查找clsid组件if( p.dll还没被装入内存{...\}DLL ...\}DLL创建类厂对象COMIClassFactoryCOMIClassFactory接口客户pClf->CreateInstance(NpClf->CreateInstance(NIID_IUnknown,(void**)&pUnknown);类厂对象的CreateInstance函数被调用(通过组件的vtable被客户直接调用)用new操作符构造字典组件对象newCDictionary;返回IUnknown接口指针客户使用字典组件,通过其接口进 ppClf->Release();pUnknown->Release();CoFreeUnusedCoFreeUnused组件对象的Release函数被调(也是通过组件的vtable)if(m_Ref==0){deletethis;return0;}COMCOM库调用字典组件的引出函数DllCanUnloadDllCanDllCanUnloadNow函数中:if不存在字典对象&&锁计数器为0)returnTRUE;returnCoCoUninitialize()if(字典组件DllCanUnloadNow数返回TRUE)CoFreeLibrary(...);COMCOM库释放资源客户程序退出客户程序退出进程外组件与客户的协作过 COMCOM组件程序CLSIDclsidIClassFactory*pClf;IUnknown*pUnknown;"...",(void**)&pClf);

COM 表中组件对象COMclsidif(EXE||COM需要另一个实例{ 表中获取EXE组件名}调用创建组件支持的各种调用COM调用COM所有类厂对象等组件完成后COM库IClassFactory接口返回给客(void类厂对象的CreateInstance函数调用(通过进程中 对象被构造组件对IUnknown客户使用字典组件,通过其接(间接)进 组件对象的Release函数被调if(m_Ref=={deletethis;return0;}如果满足退出条 常退客户程序退

放的对象调用Release函数COM

CoUninitialize组件程序退自由作读程 或者“Inside 复习:对象创建过}

TreeView{6B7E6392-850A-101B- 复习:类厂(Class 特殊性 复习:类厂(续字字典组类字典对多对象、多类厂组类厂对象复习:COM创建函复习:COMCOM库的初始COM库的内存管组件程序的装载和卸常用函数和实现COM对 实现类厂对 实现DllGetClassObject、(可选)实现两 函可重用性(reuse,复用COM重用模型:包容和聚C++类的重用模前提:假设有一个基类做法:两种模classCNewClass:publicCOldClassC++类的两种重用模COM重用模前提:假设有一个COM对象目标:实现一个新对象B,要求重用对象的功能,而不是重新实现原来已有的功做法:两种模COM包容模客户程调调包容模型说外部对象的接口与内部对象的接口可以不客户看不到内部对聚合模对象聚合模型说聚合对象和被聚合对象协同工客户直接与内部对象交互,但它并不知唯一性 的基本要重用针对某个接口而言,聚合和包容并,在一个对象上可以同时使聚合和包容的选择策包容模型实定义接口classISomeInterface:public{virtualHRESULTstdcallSomeFunction()=classIOtherInterface:public{virtualHRESULTstdcallOtherFunction()=

classCB:publicISomeInterface,public{外部

CB(~CB

象定

HRESULT stdcallQueryInterface(constIID&iid,voidULONG stdcall stdcall//ISomeInterfacemembers stdcallSomeFunction();//IOtherInterfacemembersHRESULT stdcallOtherFunction();HRESULTprivateCB::CB({m_pSomeInterface=NULL;m_Ref=0;}CB::~CB({if(m_pSomeInterface!=}{HRESULTresult=::CoCreateInstance( CLSCTX_INPROC_SERVER,IID_ISomeInterface,(void**)&m_pSomeInterface);if(FAILED(result)) returnS_OK;}HRESULT stdcallCB::SomeFunction({}HRESULT_stdcallCB::OtherFunction({}constIID&iid,void{CB HRESULT if(pUnknownOuter!=NULL)returnCLASS_E_NOAGGREGATION;pObj=newCB();if(pObj==NULL)returnhr=pObj->Init();if(FAILED(hr)){deletepObj;}//Obtainthefirstinterfacepointer(whichdoesanAddRef)hr=pObj->QueryInterface(iid,ppv);return}包容:灵活应用包容模HRESULT_stdcallCB::SomeFunction({if(...{return}{}}聚合实要点:外部对象完全重用内部对象的接关键在于外部对象的QueryInterface函 有两个函数intFunc1(intx,inty){returnintFunc2(intx,inty){returnint(*MyFunc)(int,MyFunc=inta=MyFunc(10,MyFunc=intb=MyFunc(10,

classvirtualvoid stdcallMethod1(int,int)=0;virtualvoid stdcallMethod2(int)=0;classvirtual

stdcallOperator1(int,int)=virtual stdcallOperator2(int)=

classCMyObject:publicvirtualvoid stdcallMethod1(int,int);virtualvoid stdcallMethod2(int);实例化CMyObjectVtable1*p1=–指针类型并不

p1->Method1(a,Vtable2*p2=(Vtable2*)p1;p2->Operator1(a,b);回顾:聚合模对象classCB:public{ CB(对~CB对

象HRESULT stdcallQueryInterface(constIID&iid,void**ppv);ULONG stdcall象 stdcall义 stdcallOtherFunction()义HRESULTprivateIUnknown*m_pUnknownInner;//pointertoA'sHRESULTCB::QueryInterface(constIID&iid,void{if(iid==IID_IUnknown)*ppv=(IUnknown*)this;((IUnknown*)(*ppv))->AddRef()}elseif(iid==IID_OtherInterface)*ppv=(IOtherInterface*)this;((IOtherInterface*)(*ppv))->AddRef();}elseif(iid==IID_SomeInterface)returnm_pUnknownInner->QueryInterface(iid,ppv)}else*ppv=returnE_NOINTERFACE}return}对象对象 对象 接对对象外部对象客户程对象委控点聚合模型的点如果pUnkOuter参数非NULL,并且外部对象请求(续这些要点指导我们如何实现聚合对HRESULTCoCreateInstance(constCLSID&IUnknownconstIID&iid,(voidHRESULTconstIID&iid,void两

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论