《C++高级编程课程讲义.ppt》由会员分享,可在线阅读,更多相关《C++高级编程课程讲义.ppt(89页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、C+高级编程高级编程OverviewnModule 1:面向过程的面向过程的C+nModule 2:面向对象的面向对象的C+uModule 1:面向过程的面向过程的C+n从从C到到C+n内存管理内存管理n数组数组n字符集和字符串字符集和字符串n指针和引用指针和引用n函数函数n其它其它从从C到到C+n语法增强语法增强l新的运算符l变量声明更加灵活l函数重载l引用l类型安全性n面向对象面向对象l封装l继承l多态内存管理内存管理n在在stack(栈栈)上分配内存上分配内存l简单数据类型l不使用new创建对象实例l函数调用完成自动销毁n在在Heap(堆堆)上分配内存上分配内存lmalloc还是new?
2、l检测内存泄漏l防止”野指针”:回收内存后指针会自动为NULL吗?nDemo:动态扩充的字符串缓冲区动态扩充的字符串缓冲区数组数组(1)声明及初始化声明及初始化inta=1,2,3;intb3=1,2,3;intc5=1,2,3;/c3和c4的值默认为0 inta123=1,2,3,4,5,6;inta223=1,;/初始化,第一行为1,0,0;第二行为0,0,0inta33=,1,2,3;inta42=1,2,3,4,5,6;/错误。必须声明第二维的数目inta53=1,2,3,4,5,6;/正确数组数组(2)数组的内存形式数组的内存形式n数组在内存中的存放数组在内存中的存放l全局数组在静态
3、存储区域中存放l局部数组,一般在堆栈上存放l在堆上动态分配内存double*p=newdouble10;intn=10;double*p=newdoublen;/n不必是常量double*p=newdouble400300;/错误double*p=newdouble400300;/错误数组数组(3)指针表现形式指针表现形式n一维数组指针表示一维数组指针表示n二维数组指针表示二维数组指针表示l行地址和列地址constintARRAY_SIZE=5;intaARRAY_SIZE=1,2,3,4,5;int*p=a;考察:(1)a+i,p+i,*(a+i),*a+i,pi的含义(2)p+偏移几个字节
4、?a+呢?inta3=1,2,3,4,5,6;考察:a,a+i,*(a+i),*(a+i)+j,*(*(a+i)+j),&aij的含义a+i表示二维数组a的第i行的地址,*(a+i)表示指向i行ai0首指针,*(a+i)+j是指向元素aij的指针,*(*(p+i)+j)表示读取的元素的内容数组数组(4)二维数组的指针表示二维数组的指针表示n使用一级指针访问二维数组使用一级指针访问二维数组n使用指向一维数组的指针来访问二维数组使用指向一维数组的指针来访问二维数组inta3=1,2,3,4,5,6;int*p=a0;/将二维数组展开成一维数组的方式访问int*p=a;/错误!考察:p+i,*(p+
5、i),*p+i的含义int(*p)3=a;/也可写成:int(*p)3(a);int*p3=a;/错误!Int*p3;考察:p,p+i,*(p+i),*p+i,*(p+i)+j,*(*(p+i)+j)的含义数组数组(5)动态创建复杂数组动态创建复杂数组n二维数组二维数组n交错数组交错数组intm=2;intn=3;int(*p)3=newint23;deletep;int*pm;/p数组包含两个元素,每个元素都是int*类型p1=newint3;/通过pi来操作每个数组deletep1;/不能使用deletep或者deletep字符集和字符串字符集和字符串(1)字符编码字符编码nANSI、UN
6、ICODE和和UTF-8lMultiByte和WideCharlwchar_t,“L”前缀,wcslen,wcscpy,wcslenn字符集的转换字符集的转换lmbstowcs_s和wcstombs_slMultiByteToWideChar,WideCharToMultiBytewchar_tp1=L“abcd”;考察:wcslen(p1)和sizeof(p1)的结果wchar_tp1=Labcd;charp210;intlen=wcstombs(p2,p1,sizeof(p1);/len=40字符不计入拷贝字符数目wchar_t*p3=(wchar_t*)malloc(100);mbsto
7、wcs(p3,p2,100);字符集和字符串字符集和字符串(2)兼容字符集兼容字符集nWindows平台与字符集平台与字符集nVisual C+编译器字符集设置选项编译器字符集设置选项l_UNICODEl_MBCSn兼容字符集兼容字符集lTCHAR,_tcslen,“_T”TCHARt=_T(aaa);/如果编译器定义了_UNICODE,sizeof(t)=8,/如果定义了_MBCS,sizeof(t)=4字符集和字符串字符集和字符串(3)声明字符串声明字符串n使用指针使用指针n使用数组使用数组char*p1=abcd;char*p2=abcd;考察:内存中有几个”abcd”存在,p1=p2是
8、否成立?charp110=a,b,c,d,0;/注意结尾的0charp2=“abcd”;/自动添加0结尾charp3=“abcd”;charp4=a,b,c,d;/仅仅声明一个字符数组而非字符串考察(1)sizeof(p),strlen(p)的值分别是多少?(2)p2=p3?/false字符集和字符串字符集和字符串(4)字符串操作函数字符串操作函数n修改单个字符修改单个字符n字符串长度字符串长度n模拟编写模拟编写strcpy方法方法l为何采用const作为参数l为何返回char*l0会被拷贝吗?lDemocharp110=“abcd”;char*p2=“abcd”;/p2指向常量字符串p10=
9、x/OKp20=x/错误,常量字符串不可修改charp1=atnc;考察:strlen(p1)和sizeof(p1)指针与引用指针与引用(1)概念概念n指针与指针变量指针与指针变量n引用的定义引用的定义l引用必须在声明时立即初始化,不允许空引用l引用一旦初始化,就不能再引用其它数据l引用和被引用的变量实际上代表同一个内存的数据doublea=10;double*p=&a;考察:(1)p是指针变量,则sizeof(p)=?(2)&p含义是什么?/p的内存地址inta=100;int&b=a;b=1000;考察:(1)&a与&b的关系?(2)a=?指针与引用指针与引用(2)混合使用混合使用n指针指
10、向某个引用指针指向某个引用n引用一个地址引用一个地址doublea=100;double&b=a;double*p=&b;考察:(1)&a,p和&b的关系(2)修改a,b或*p的值,另两个是否联动doublea=100;double&b=a;double*p=&b;double*&rp=p;/p和rp是完全相同的,且都是变量a的地址考察:sizeof(b)=?sizeof(rp)=?指针与引用指针与引用(3)作为参数传递作为参数传递n按值传递按值传递n按地址传递按地址传递n按引用传递按引用传递voidIncrease(int&data)data+;voidmain()intmydata=10;
11、Increase(mydata);指针与引用指针与引用(4)指针与常量指针与常量n指向常量的指针指向常量的指针n指针常量指针常量inta=100;intb=200;constint*pci=&a;/pci不能直接修改a地址中的数据a=1000;/可以通过修改a的数据从而间接修改*pci*pci=1000;/错误pci=&b;/OK.Pci可以指向另一个地址,不再与a相关考察:如果a被定义为:constinta=100,那么:int*pci=&a;是否成立?/error可改:constint*pci=&a;inta=100;intb=200;int*constpci=&a;/pci不能再指向别的
12、地址*pci=1000;/可以通过修改*pci来修改a的数据pci=&b;/错误考察:如果有constint*constpci=&a,则情况如何?/right指针与引用指针与引用(4)引用与常量引用与常量n将一个引用设置为常量后,不能通过该引用修改数将一个引用设置为常量后,不能通过该引用修改数据;但仍可通过被引用的变量来改变:据;但仍可通过被引用的变量来改变:n被引用的数据是常量,引用本身也必须是常量:被引用的数据是常量,引用本身也必须是常量:inta=100;constint&b=a;/b与a是同一内存,但不能直接修改bb=1000;/错误a=1000;/OKconstinta=100;co
13、nstint&b=a;/OKint&b=a;/错误指针与引用指针与引用(5)Practicechars1=abcdefg;chars2=1234567;char*p1=s1;constchar*p2=s1;char*constp3=s1;constchar*constp4=s1;考察:下列哪些语句有效:p10=k;p20=k;p30=k;p1=s2;p2=s2;p3=s2;p4=s2;函数函数(1)ExternnC语言中的语言中的Extern和和StaticnC+中的中的extern“C”l允许在C+中调用C编写的函数l允许在C中调用C+编写的函数nDemo:如何在如何在C+和和C之间实现互操
14、作之间实现互操作cfile.h文件:externintadd(intx,inty)cfile.c文件:intadd(intx,inty)returnx+y;cpp.cpp:extern“C”#include“cfile.h”其它格式:extern“C”intadd(intx,inty);extern“C”intadd(intx,inty);intsub(inta);函数函数(2)函数指针函数指针n声明原型声明原型n指针赋值指针赋值n函数调用函数调用n函数指针作为参数传递函数指针作为参数传递int(*fun)(intx,inty);或者int(*fun)(int,int);设存在函数intmax
15、(inti,intj)int(*fun)(int,int)(max);或者fun=max;(*fun)(10,20);voidprocess(intx,inty,int(*f)(int,int)process(10,20,max);nvoid f1(int,int);nvoid f2(int,int);nvoid fn(int,int,void(*)(int,int);nint main()nnvoid(*fun)(int,int);nint a=10,b=5;fun=f1;(*fun)(a,b);nfun=f2;(*fun)(a,b);nfn(a,b,f2);nreturn 0;nnvoid
16、 f1(int a,int b)nncouta+b=a+bendl;nnvoid f2(int a,int b)nncouta-b=a-bage=10;/通过指针修改a参数和返回值参数和返回值(4)返回对象实例返回对象实例ACreateA()Aobj;/在堆栈创建局部对象obj.age=10;returnobj;/obj被拷贝给一个临时对象tmp/函数结束,堆栈弹出,局部对象obj被销毁调用:Aa;/调用A的默认构造函数a=CreateA();/调用a的赋值函数将tmp对象赋给aAb=CreateA();/情况会有所不同,obj直接通过拷贝构造函数拷贝给bn理解隐含的构造函数、拷贝构造函数、赋
17、值函数调用理解隐含的构造函数、拷贝构造函数、赋值函数调用参数和返回值参数和返回值(5)返回对象指针返回对象指针n返回无效的对象指针返回无效的对象指针A*CreateA()Aobj();obj.age=10;return&obj;/obj将被销毁,因此返回的地址实际上没有意义调用:A*p=NULL;/这不会引起调用A的默认构造函数p=CreateA();/没有临时对象产生,没有拷贝构造函数和赋值函数调用考察:既然p得到的地址没有意义,为什么有些情况下通过p来访问对象的数据,仍然可以成功呢?参数和返回值参数和返回值(6)返回对象指针返回对象指针n返回有效的对象指针返回有效的对象指针A*Create
18、A()A*pObj=newA();pObj-age=10;returnpObj;/由于pObj分配再堆而不是堆栈上,因此不会被自动销毁调用:A*p=NULL;/这不会引起调用A的默认构造函数p=CreateA();delete p;/释放内存释放内存参数和返回值参数和返回值(7)返回对象引用返回对象引用n返回对象引用可以避免临时对象的产生返回对象引用可以避免临时对象的产生n但是要特别注意,不要返回无效的引用但是要特别注意,不要返回无效的引用A&CreateA()Aobj;obj.age=10;returnobj;/obj将被销毁A&b=CreateA();/b引用obj,但obj已经销毁,因此
19、b无效考察:为什么赋值函数中可以并且应该返回引用?参数和返回值参数和返回值(8)编写高效的编写高效的returnn直接在直接在return语句中构造对象将有助于减少临时对语句中构造对象将有助于减少临时对象的创建和销毁象的创建和销毁 AGetA()/Aa(10);/创建临时对象/returna;/调用拷贝构造函数将临时对象赋给obj,然后销毁临时对象returnA(10);/直接把临时对象创建在obj的内存单元中Aobj=GetA();const修饰符修饰符(1)修饰参数和返回值修饰参数和返回值n修饰参数修饰参数l编译器确保该参数在函数内不会被修改n修饰返回值修饰返回值l返回结果是常量,不能修改
20、考察:f(inti)与f(constinti)有何区别?constcomplexoperator+(constcomplex&c1,constcomplex&c2)returncomplex(c1.real+c2.real,c1.image+c2.image);考察:(1)c1和c2声明为常量引用有什么好处?(2)设obj1,obj2,obj3都是complex,则(obj3+obj2)=obj1是否合法?(3)函数为什么不返回一个引用?const修饰符修饰符(2)常函数常函数n对于一个不会修改数据成员的类成员函数,建议声对于一个不会修改数据成员的类成员函数,建议声明为常函数明为常函数 l常量
21、实例只能调用函数的const版本l非常量实例一般调用函数的非const版本l如果一个函数只有const版本而没有非const版本,那么非常量实例可以调用const版本lConst函数内部不能再调用非const函数intGetModule()returnreal*real+image*image;intGetModule()constreturnreal*real+image*image;如果:complexc1(1,2);c1.GetModule(),则调用非constconstcomplexc2(1,2);c2.GetModule(),则调用const运算符重载运算符重载(1)实现方式实现方
22、式n重载为类实例成员函数重载为类实例成员函数n重载为友元函数重载为友元函数n考察:重载了考察:重载了”+”后,还需要重载后,还需要重载”+=“吗?吗?Complex&operator+=(Complexc)this.real+=c.real;this.image+=c.image;return*this;friendComplexoperator+(Complex&c1,Complex&c2)/友元是全局函数,应该生成新对象返回,而不能返回*thisreturnComplex(c1.real+c2.real,c1.image+c2.image);运算符重载运算符重载(2)+操作符操作符clas
23、sCountpublic:intnum;Count():num(0)Count&operator+()/+作为前缀操作符num+;return*this;Countoperator+(int)/在一定程度上模拟+作为后缀操作符Counttemp=*this;/注意编写拷贝构造函数num+;returntemp;/返回一个临时对象,模拟先运行,再+操作;重载运算符重载运算符(3)编写类型转换函数编写类型转换函数Complexoperator=(doubled)/允许double隐式转换成Complexthis-real=0.0;this-image=0.0;operatordouble()ret
24、urnreal;/允许Complex隐式转换成double调用:Complexc;c=2.0;doubled=c;考察:(1)能否写成:Complexc=2.0?如何允许这种写法?(2)区别隐式转换与赋值函数n运算符重载运算符重载Demo:复数类复数类虚函数虚函数(1)多态多态 classShapepublic:voidDraw();/基类classRectangle:publicShapeclassEllipse:publicShapepublic:voidDraw();public:voidDraw();不应用多态:考察:如果有N个子类?voidDraw(Rectangle*pRec)pR
25、ec-Draw();voidDraw(Ellipse*pEll)pEll-Draw();应用多态:voidDraw(Shape*pShp)pShp-Draw();虚函数虚函数(2)virtual关键字关键字n如果基类函数没有如果基类函数没有virtual关键字?关键字?n静态联编静态联编n动态联编动态联编n子类函数还需要编写子类函数还需要编写virtual吗吗?n为什么析构函数要写成为什么析构函数要写成virtual?n纯虚函数和抽象类纯虚函数和抽象类n防止内存泄露n如:A*a=newC();/A为基类ndeletea;n对上面的语句,如果基类的析构函数不为virtual,则不会释放Cn静态联
26、编支持的多太性称为编译时多太态性。通过函数重载和模板体现。n动态联编支持的多态性称为运行时多态性,通过继承和虚函数来实现。虚函数虚函数(3)区分重载区分重载/重写重写/隐藏隐藏nOverloadl同一个类中同名但不同参数的函数nOverridel子类重新实现基类继承的虚函数l子类函数与基类函数原型完全一致nHidel子类与基类定义了同名非虚函数且原型相同,则子类隐藏基类的函数nDemo:隐藏示例隐藏示例n在子类中调用基类被隐藏的函数n如:base:print()虚函数虚函数(4)多重继承多重继承n为什么需要多重继承为什么需要多重继承n如何避免多重继承重的二义性如何避免多重继承重的二义性l虚继承
27、nMFC中多重继承的例子中多重继承的例子n要解决二义性有两种方法:n(1)使用作用域运算符,用类名对成员加以限定。n(2)在派生类中定义同名成员,以隐藏基类成员。友元友元(1)友元函数友元函数n友元函数可以做什么?友元函数可以做什么?n友元函数可以是全局函数友元函数可以是全局函数n也可以是类成员函数也可以是类成员函数n不要使用访问限定符来修饰不要使用访问限定符来修饰friend语句语句friendintglobal_func(.);friendintsomeclass:class_func(.);/class_func本身可有访问限定符 友元友元(2)友元类友元类n类类A是类是类B的友元类,则
28、类的友元类,则类A中所有函数都可以访问中所有函数都可以访问类类B中的任何成员中的任何成员n声明友元类声明友元类nDemo:一个链表维护类一个链表维护类friendclasssomeclass;模板模板(1)模板的必要性模板的必要性voidswap(int&i,int&j)voidswap(float&i,float&j)voidswap(uint&i,uint&j)n不使用模板不使用模板n使用模板使用模板templatevoidswap(T&a,T&b).调用:inta,b;swap(a,b);floata,b;swap(a,b)模板模板(2)模板函数模板函数n单类型模板单类型模板n多类型模板
29、多类型模板n模板函数代码在哪里编写?模板函数代码在哪里编写?templatevoidSwap(T1&a,T2&b)模板模板(3)模板类模板类n类声明类声明l类中相关变量、参数和返回值类型用T代替n函数实现函数实现l可以在类声明内或外部实现l.h文件还是.cpp文件?n使用使用templateclassStackvoidpush(Ta);.;templatevoidStack:push(Ta).Stacks;n定义和函数声明都必须放在同一个h文件中,要不vc编译器会报错.但有些编译器允许模板模板(4)模板应用实例模板应用实例nC+标准模板库标准模板库nATL活动模板库活动模板库其它其它(1)局部
30、类和嵌套类局部类和嵌套类n局部类局部类l在一个函数的内部定义l所有函数体都在类声明内;不能有静态变量l可访问函数中已经声明的局部变量l不可直接访问函数所在类的成员n嵌套类嵌套类l在包容类的内部定义l嵌套类中可直接访问包容类的任何成员l包容类可以访问嵌套类的共有成员;不能访问非公成员l从包容类外部访问嵌套类成员时,访问限定取最严格集nDemo:MFC使用嵌套类实现使用嵌套类实现COM多接口多接口其它其它(2)内联函数和宏内联函数和宏n宏定义的不足宏定义的不足l编译器简单替换,不进行类型检查l容易造成歧义n内联函数内联函数l函数体直接写在类声明内l也可用inline关键字在类声明外编写(建议)#d
31、efinemax(a,b)(a)(b)?(a):(b)考察:i=5,j=0,计算max(+i,j)inlineintmax(inta,intb)returnab?a:b;其它其它(3)强制类型转换强制类型转换nstatic_castl可用于简单数据类型之间以及对象指针的转换l运行时不进行类型检查,因此不能保证转换的安全性。即使转换失败,也会返回某个地址l程序员应确保转换确实可行ndynamic_castl不能用于简单数据类型之间的转换l运行时如果转换失败,则返回NULLch=static_cast(i);/inttocharB*pb=newD;D*pd=dynamic_cast(pb);/ok
32、:pbactuallypointstoaD其它其它(4)异常处理异常处理trychar*buf=newchar512;if(buf=0)throwMemoryallocationfailure!;catch(char*str)coutExceptionraised:strn;n抛出和处理简单异常抛出和处理简单异常throwCMyException();catch(CMyexceptionex)n抛出自定义异常类抛出自定义异常类n处理多个异常处理多个异常trycatch(char*str)catch(intcode)catch()其它其它(5)n对象数组对象数组l对象数组的初始化问题nDemol
33、面向对象的C+实现:Stack类l面向对象的二叉树实现l使用多态性构造的有限状态自动机uC+设计模式设计模式n核心设计模式核心设计模式l创建型l结构型l行为型n为什么要使用设计模式为什么要使用设计模式n合理使用设计模式合理使用设计模式创建型模式创建型模式(1)简单工厂简单工厂n由一个工厂类决定创建那些由一个工厂类决定创建那些类的实例类的实例n该工厂类可以创建多个类别该工厂类可以创建多个类别的对象的对象创建型模式创建型模式(2)工厂方法工厂方法n工厂定义创建产品对象的接工厂定义创建产品对象的接口,实际的创建工作在工厂口,实际的创建工作在工厂子类中完成子类中完成n每个子类一般专门负责创建每个子类一
34、般专门负责创建一种产品。因此该子类只需一种产品。因此该子类只需要了解它所需要创建的产品要了解它所需要创建的产品类型即可类型即可nCOM的类工厂的类工厂创建型模式创建型模式(3)抽象工厂抽象工厂n抽象工厂为创造一系列产品抽象工厂为创造一系列产品提供一个抽象接口,由子类提供一个抽象接口,由子类实现具体对象的创建实现具体对象的创建n每个工厂一般负责创建一系每个工厂一般负责创建一系列列(多种多种)产品产品创建型模式创建型模式 (4)生成器模式生成器模式n将对象的创建步骤和创建细将对象的创建步骤和创建细节分开节分开n构造器负责产品各个部分构构造器负责产品各个部分构造造n导航器负责组装产品导航器负责组装产
35、品创建型模式创建型模式(5)原型模式原型模式 n对象通过赋值自己创建新的实例对象通过赋值自己创建新的实例n区分浅复制和深复制区分浅复制和深复制创建型模式创建型模式(6)单件模式单件模式n确保某个类只有一个实例确保某个类只有一个实例n由类自行实例化并提供获得实例的接口由类自行实例化并提供获得实例的接口结构型模式结构型模式(1)适配器模式适配器模式n使接口不同的两个对象能协同工作使接口不同的两个对象能协同工作l客户需要使用目标接口(目标类)l现有接口(待配类)与目标接口不一致l适配器即兼容目标,也兼容待配类n类适配器类适配器l同时继承Target和Adapteen对象适配器对象适配器l仅继承Tar
36、getl内部使用Adaptee对象结构型模式结构型模式(2)组合模式组合模式n体现体现”部分部分-整体整体”关系关系结构型模式结构型模式(3)装饰器模式装饰器模式n为对象提供功能扩展,同时保持对象的透明性为对象提供功能扩展,同时保持对象的透明性结构型模式结构型模式(4)代理模式代理模式n通过代理对象访问实际对象,从而实现对象的受控通过代理对象访问实际对象,从而实现对象的受控访问访问nCOM跨进程调用跨进程调用nWeb服务代理服务代理结构型模式结构型模式(5)享元模式享元模式n支持大量的细粒度对象,通过享元工厂控制各个享元对支持大量的细粒度对象,通过享元工厂控制各个享元对象的创建和访问象的创建和
37、访问nCOM+对象池对象池结构型模式结构型模式(6)外观模式外观模式n为具有多个接口的子系统提供一个统一的接口,以为具有多个接口的子系统提供一个统一的接口,以简化客户对该子系统的调用简化客户对该子系统的调用结构型模式结构型模式(7)桥接模式桥接模式n分离抽象与实现,从而使得它们可以独立变化分离抽象与实现,从而使得它们可以独立变化行为型模式行为型模式(1)职责链职责链n将多个对象连成一条链,并将多个对象连成一条链,并沿着链传递客户请求,直到沿着链传递客户请求,直到有一个对象处理它为止有一个对象处理它为止n多个异常的处理方式多个异常的处理方式行为型模式行为型模式(2)命令模式命令模式n将一个请求封
38、装为一个对象,使请求与接受请求的对象分离将一个请求封装为一个对象,使请求与接受请求的对象分离n还可对请求进行排队或记录请求日志,并支持可撤销的操作还可对请求进行排队或记录请求日志,并支持可撤销的操作行为型模式行为型模式(3)解释器解释器n给定一个语句,定义其语法形式;再定义一个解释器,根给定一个语句,定义其语法形式;再定义一个解释器,根据语法形式将该语句以面向对象的方式表达出来。据语法形式将该语句以面向对象的方式表达出来。n人机交互、用表达式表示的逻辑和数学运算人机交互、用表达式表示的逻辑和数学运算行为型模式行为型模式(4)迭代器迭代器n提供一种方法顺序访问一个提供一种方法顺序访问一个聚合对象
39、种的各个元素,且聚合对象种的各个元素,且不暴露该对象的内部表示不暴露该对象的内部表示nfor,foreach行为型模式行为型模式(5)备忘录模式备忘录模式n在不破坏封装性的前提下,捕获一个对象的内部状态;在该对在不破坏封装性的前提下,捕获一个对象的内部状态;在该对象之外保存这个状态,以便以后可以恢复到原先保存的状态象之外保存这个状态,以便以后可以恢复到原先保存的状态行为型模式行为型模式(6)状态模式状态模式n使对象在不同的状态下改变其行为使对象在不同的状态下改变其行为n对象在不同的上下文中,相同的动作导致的结果不同对象在不同的上下文中,相同的动作导致的结果不同行为型模式行为型模式(7)观察者模
40、式观察者模式n定义对象间一对多的依赖关系,当一个对象发生变化使,定义对象间一对多的依赖关系,当一个对象发生变化使,所有以来它的对象都得到通知并自动更新所有以来它的对象都得到通知并自动更新nMFC中的文档中的文档/视结构视结构行为型模式行为型模式(8)中介者模式中介者模式n用一个中介对象将一系列对象交互封装,从而降低这些对象用一个中介对象将一系列对象交互封装,从而降低这些对象间的耦合性并可以独立的改变对象间的交互关系间的耦合性并可以独立的改变对象间的交互关系n用户界面上多个控件之间的交互用户界面上多个控件之间的交互行为型模式行为型模式(9)策略模式策略模式n将算法封装,使系统可以更换或扩展算法。
41、将算法封装,使系统可以更换或扩展算法。n所有子类的目标一致,但实现的方法不同。所有子类的目标一致,但实现的方法不同。n加密算法加密算法n使用函数指针的策略模式使用函数指针的策略模式行为型模式行为型模式(10)模板方法模式模板方法模式n定义一个操作中的算法的骨架,将实现延迟到子类中定义一个操作中的算法的骨架,将实现延迟到子类中n模板方法是代码复用的基本技术模板方法是代码复用的基本技术n关于虚函数关于虚函数行为型模式行为型模式(11)访问者模式访问者模式n实现通过统一的接口访问不同类型元素的操作,并且通过这实现通过统一的接口访问不同类型元素的操作,并且通过这个接口可以增加新的操作而不改变各元素的类。个接口可以增加新的操作而不改变各元素的类。n关于友元关于友元