面向对象方法与技术:面向对象的程序设计_第1页
面向对象方法与技术:面向对象的程序设计_第2页
面向对象方法与技术:面向对象的程序设计_第3页
面向对象方法与技术:面向对象的程序设计_第4页
面向对象方法与技术:面向对象的程序设计_第5页
已阅读5页,还剩97页未读 继续免费阅读

下载本文档

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

文档简介

共102页第1页面向对象方法与技术共102页第2页第五部分面向对象的程序设计5.1面向对象程序设计原则5.2面向对象程序设计语言5.3面向对象程序设计实例5.4面向对象程序设计中的高级技术面向对象的程序设计思想出现于60年代末期,以Simula语言为标志。发展到80年代出现了Smalltalk等,直至出现C++、Java等,面向对象程序设计的思想逐渐被人们所广泛接受,目前已经成为程序设计领域的主流。共102页第3页5.1面向对象程序设计的原则5.1.1复用性5.1.2可扩充性5.1.3健壮性5.1.4协作性面向对象程序设计:使用程序设计语言将设计方案加以表达类定义静态模型动态模型类的实现约束实现于代码中增强系统健壮性共102页第4页5.1.1复用性加强软件可复用性的原则:保证操作的内聚性

功能相对单一减少单一功能模块代码规模

函数代码的适当规模保证操作对外接口的一致性

相似操作具有一致性接口分离设计中的操作与实现中的操作

以相对单一和基本的操作联合实现设计中的操作操作均匀覆盖数据

考虑操作的普适性加强封装

操作只针对内部数据,实现与接口分离减少操作耦合

减少操作之间的相关,尽量上下文无关共102页第5页在校人员类姓名年龄系别教师类工资学生类班主任姓名年龄系别工资班主任在校人员类5.1.1复用性复用方式:继承聚集电视类家电类型号外观颜色生产厂家显像管型号冰箱类压缩机型号冰箱类型号外观颜色生产厂家显像管型号电视类型号外观颜色生产厂家显像管型号提取公共代码分离部分成员区分子类与继承封装外部代码CPointxyCRectanglexyrCPointxyCRectangler共102页第6页5.1.2可扩充性继承和多态机制支持程序具有很强的可扩充性。增强可扩充性的原则:封装数据封装操作内的数据结构减少耦合性避免情况选择语句区分公有操作和私有操作共102页第7页5.1.3健壮性误操作及错误输入数据情况下对象保持状态行为正确的能力。程序设计中考虑健壮性的原则:防止输入错误把握优化代码的时机选择恰当的实现方法检测参数的合法性推迟对内存分配的限制定义一个类(包括年、月、日)。计算该日是本年中第几天?(注意闰年问题,)。运行结果示例:请输入日期(年,月,日):1990,9,209月20日是1990年的第263天。共102页第8页5.1.4协作性intMyFunction(char*pName,intMark){//Function :Demonstratehowtowritecomment//Parameter :pName,thenameofastudent// Mark,thescoreofstudentpName//Global : xxxx//Algorithm : yyyyyyy//Writer : Wangming//Date : 2002-8-9//note :xxxx……}共102页第9页5.2面向对象程序设计语言5.2.1Smalltalk语言5.2.2Eiffel语言5.2.3C++语言5.2.4Java语言共102页第10页5.3面向对象程序设计实例5.3.0C++基本语法5.3.1类的定义5.3.2对象的创建及初始化5.3.3消息传递与操作调用5.3.4继承5.3.5关联的实现5.3.6聚集关系的实现5.3.7多态性5.3.8运算符重载5.3.9静态成员本节以C++语言为例展示如何将OOA和OOD中的类、对象、类间三种关系以具体语言方式加以实现。共102页第11页5.3.0C++基本语法1VisualC++环境环境定制:项目创建:程序编辑:编译与调试共102页第12页1VisualC++环境创建项目项目(Project,亦称工程)的创建是使用集成开发环境编写程序的第一步,一个项目由一组相关联的文件组成,包括用户将来自己编写的源程序文件和系统自动创建的一系列文件(用于调试程序、浏览程序中各种信息、目标文件等),它们被放置在某个目录下,由开发环境进行管理。如果项目已经存在,可以通过开发环境中File菜单下的菜单项OpenWorkspace打开,否则必须新创建,具体创建步骤如下:单击File

→单击New

→图5.3.a在Projectname编辑框中键入所要编写的项目名(将来生成可执行文件的主文件名与此相同)。选择该工程所在位置。在Location编辑框中键入放置该项目的磁盘目录,应该键入全路径名。选择项目的类型。选择Win32ConsoleApplication则创建控制台应用程序,相当于创建dos应用程序,只不过所创建程序的输入输出限制在一个控制台窗口(类似Windows下的命令提示符窗口)中,而不是整个屏幕。单击OK按钮后,屏幕上将弹出对话框,如图5.3.b最方便的选择是创建一个“Asimpleapplication”。当选择最后一个选项时,在所创建的程序中将可以使用MFC类库中定义的一些数据结构,如动态字符串CString和哈希表等,这将给编程带来方便。共102页第13页图5.3.a图5.3.b1VisualC++环境共102页第14页程序编辑:键入、剪切、拷贝、粘贴、查找、全程查找、书签的使用创建一个项目后该项目被打开,这个项目中可能是空的,一个文件都没有,用户需要在项目中添加自己的文件,方法如下:选择开发环境中Project菜单下的菜单项AddToProject后,会出现一个popup菜单,如果所要添加的是一个尚未编辑的新文件则选择菜单项New,否则选择Files。在所弹出的对话框中选择将要添加的文件的类型为C/C++HeaderFile或C++SourceFile,然后键入文件名,确认后相应文件的编辑窗口被打开,编程者就可以在其中编辑程序,编辑操作如同在使用MicrosoftWord或Wordpad等一样方便。1VisualC++环境共102页第15页编译与调试:编译、运行,断点、单步、观察变量值程序全部或部分编写完成后需进行编译后才能运行。编译后程序一般都会出现多个语法错误,需要根据Output窗口中的提示信息对程序进行重新修改,直到编译后不再出现错误为止。程序的编译可以选择开发环境的Build菜单下的Compile...菜单项或Build...菜单项,两者的区别在于Compile只编译当前获得焦点的文件,而Build则编译所有受到当前激活文件内容改动影响的文件,而且一旦编译通过,将所调用的系统函数与程序的目标代码进行联接,最终形成可执行的exe文件。#include<iostream.h>voidPrintString(char*szStr){cout<<"Hellow,"<<szStr<<"!"<<endl;}voidmain(){charpName[80];//User'snamecout<<"Enteryournameplease:";cin>>pName;PrintString(pName);}1VisualC++环境共102页第16页5.3.0C++基本语法2C++程序基本结构#include<iostream.h>voidPrintString(char*szStr){cout<<"Hellow,"<<szStr<<"!"<<endl;}voidmain(){charpName[80];//User'snamecout<<"Enteryournameplease:";cin>>pName;PrintString(pName);}文件包含预处理、函数、主函数、语句、标准输入、标准输出共102页第17页5.3.0C++基本语法3C++的基本数据类型intfloatdoublecharTYPE*TYPE&intn=9542; 4Bytesintm(120;) 4Bytescharc=97; 1BytesboolmBool(true); 1Bytes变量:变量是程序运行过程中可以改变其值的数据对象,变量在程序中作为数据信息载体,可以用来保存非持久数据、存储运算结果、也可以为程序块之间传递数据信息。一个变量具有名字、类型和值三要素

变量数据 常量变量的值可在程序运行过程中通过赋值语句加以改变

n=n+1234; m=ox_2345 c=‘a’; mBoo=false;共102页第18页5.3.0C++基本语法3C++的基本数据类型是程序执行过程中其值不能被改变的数据对象常量字面意义就是它所代表的常量值字面量符号常量用一个标识符代表某个具体常量,出现在程序中的将是这个标识符,而不是与这个标识符相联系的常量

231、0x3A 、07351.23、3.141e-8’a’、’\n’、’065’、’0xFA’"MynameisJohn"

constintnTopIndex=10;constcharcVisible='y';constchar*MyName="Frank";intnA;intnB;intnC;cout<<“inputA:“;cin>>nA;cout<<“inputB”;cin>>nB;nC=nA+nB;输入两个整数,求它们的和共102页第19页5.3.0C++基本语法4C++的基本操作+-*/&&||!&|~%赋值语句简单赋值语句:n=8;x=3*6+4/a;复合赋值语句:n+=2;共102页第20页5.3.0C++基本语法5C++语句间顺序控制if(a==0)x=1;elsex=2条件语句if(a==8)b=9;else{if(a==9)b=20;else{if(a==10)b=21;elseb=30;}}b=20b=9b=30b=21a==8a==9a==10falsefalsefalsetruetruetrueif语句()布尔表达式if语句语句else共102页第21页switch(x){case1:a==0;break;case2:x=2break;}5.3.0C++基本语法5C++语句间顺序控制开关语句}<语句>:defaultswitch语句()switch<整型表达式>{<整型常量表达式><语句>case:共102页第22页for(inti=n;i>0;i--)n*=i;5.3.0C++基本语法5C++语句间顺序控制inti(n);do{n*=i;i--;}while(i>0)inti(n);while(i>0){n*=i;i--;}循环语句for语句(for<表达式1>;<表达式2>;<表达式3>)<语句>while句(while<表达式>)语句do语句(while<表达式>)<语句>do求一个不很大的自然数n的阶乘(调试)共102页第23页5.3.0C++基本语法6数据控制函数参数表类型参数名空格,()函数头返回值类型函数名参数表函数函数头函数体函数体{}语句doubleGetProduct(doublex,doubley){doubletemp=x*y;returntemp;}voidmain(){inta=1.2,b(2.1);cout<<GetProduct(a,b)<<endl;}共102页第24页5.3.0C++基本语法6C++中的数据控制传值调用#include"iostream.h"voidSwap(intp,intq){inttemp=p;p=q;q=temp;cout<<"p="<<p<<",q="<<q<<endl;}voidmain(){intx=2,y=3;Swap(x,y);cout<<"x="<<x<<",y="<<y<<endl;}#include"iostream.h"voidSwap(int*p,int*q){inttemp=*p;*p=*q;*q=temp;cout<<"*p="<<*p<<",*q="<<*q<<endl;}voidmain(){intx=2,y=3;Swap(&x,&y);cout<<"x="<<x<<",y="<<y<<endl;}对于传值调用,在函数调用进行形实结合时,形式参数被赋予实在参数的(右)值,而在函数体中形式参数等价于函数内定义的变量。由于形参仅被赋予了实参的右值,因此形参的任何变化不会引起实参的改变共102页第25页5.3.0C++基本语法6C++中的数据控制引用调用 传址调用#include"iostream.h"voidSwap(int&p,int&q){inttemp=p;p=q;q=temp;cout<<"p="<<p<<",q="<<q<<endl;}voidmain(){intx=2,y=3;Swap(x,y);cout<<"x="<<x<<",y="<<y<<endl;}#include"iostream.h"intfunc(inta[]){a[2]=8;return0;}voidmain(intargc,char*argv[]){intb[]={1,2,3,4,5};func(b);cout<<b[2]<<endl;}形式参数和实在参数代表内存中同一个数据对象,因此在函数调用进行形实结合时,形式参数被赋予实在参数的(左)值,因此形式参数的任何变化都会引起实在参数的改变引用调用方式将作为实参的表达式的左值传递给被调函数,在实现时相当于以实在参初始化相应的引用类型参数,为实在参数建立一个别名,使形式参数和实在参数代表内存中的同一个数据对象

共102页第26页7内联函数引例:编写一个函数比较两数大小intmin(intv1,intv2){ return(v1<v2?v1:v2);}5.3.0C++基本语法共102页第27页为什么要定义一个min()函数?易于理解改变一个局部化的实现比更改一个应用中的300个出现要容易得多语义统一,可被重用。问题:函数的调用需要开销。7内联函数5.3.0C++基本语法共102页第28页用内联函数解决问题若一个函数被指定为内联函数,则它将在程序中每个调用点上被“展开”

intval=min(i,j);

被展开为:

intval=i<j?i:j;7内联函数5.3.0C++基本语法共102页第29页内联函数的使用范围被频繁调用的功能函数体简单需要高效率使用内联函数的缺点:可执行程序文件尺寸增大7内联函数5.3.0C++基本语法共102页第30页8默认形参值的函数函数参数可以指定默认值,称为默认参数。floatArea(floatWidth,floatLength=12.0)其中,我们只用一个参数调用此函数:

floata;a=Area(6.5);5.3.0C++基本语法共102页第31页C语言中,要用不同的函数名定义相同作用的不同类型函数intcube(intnumber){…}//求整数立方floatfcube(floatnumber)){…}//浮点数立方doubledcube(doublenumber){…}//求双精度数立方调用立方计算函数需要分别不同的类型函数.C++用相同的函数名定义不同类型的相同作用函数intcube(intnumber){…}floatcube(floatnumber){…}doublecube(doublenumber){…}调用立方计算函数用统一的函数名.9函数重载5.3.0C++基本语法共102页第32页代码区(codearea)全局数据区(dataarea)堆区(heaparea)栈区(stackarea)存放程序代码存放程序的全局数据和静态数据存放程序的动态数据存放程序的局部数据程序的内存区域10动态存储:new&delete5.3.0C++基本语法共102页第33页5.3.1类的定义1.类说明:class<ClassName>{private:

私有数据和函数

public:

公有数据和函数

protected:

受保护数据和函数};

CBookm_pczName:char*=“程序设计”nTotalPage:int=280nEdition:int=2char*GetBookName();intGetTotalPage();intGetEdition();classCBook{public:char*m_pczName;intnTotalPage;intnEdition;char*GetBookName();intGetTotalPage();intGetEdition();};私有成员只能被其自身成员所访问公有成员可以被任何函数所引用保护成员只能在该类的派生类类体中使用共102页第34页5.3.1类的定义2.成员函数定义:char*CBook::GetBookName(char*pStr){strcpy(pStr,m_pczName);returnpStr;}classCBook{public:char*m_pczName;intnTotalPage;intnEdition;char*GetBookName();intGetTotalPage();intGetEdition();};成员函数的定义除必须指明函数所属类外,与一般的函数定义类似:classCBook{public:char*m_pczName;intnTotalPage;intnEdition;char*GetBookName(){strcpy(pStr,m_pczName);returnpStr;}intGetTotalPage()intGetEdition();};内联函数共102页第35页5.3.2对象的创建及初始化1.由类创建对象实例classCPoint{private:intm_x;intm_y;public:void SetXY(intx,inty){m_x=x;m_y=y;}intGetX(){returnm_x;}intGetY(){returnm_y;}};从类产生解空间对象的过程是一个从一般到特殊的演绎过程,这个过程在C++中有相对应的语法——对象定义。定义对象象定义一个普通变量一样,只不过这里将类看做是类型(一个抽象类型),具有该类类型的变量称为对象:voidmain(){CPointMyPoint1,MyPoint2; //创建对象,调用缺省构造函数初始化

MyPoint1.SetXY(2,3); //设置MyPoint1的属性值分别为2和3MyPoint2.SetXY(4,5); //设置MyPoint2的属性值分别为2和3intx=MyPoint1.GetX(); //调用成员函数得到数据成员m_x的值

inty=MyPoint1.GetY(); //调用成员函数得到数据成员m_y的值

cout<<x<<";"<<y<<endl;cout<<MyPoint2.GetX()<<";"<<MyPoint2.GetY()<<endl;

CPoint*pPoint; //定义指向CPoint类对象的指针

pPoint=&MyPoint2; //将对象MyPoint2的地址赋值给pPointx=pPoint->GetX(); //通过指针调用成员函数

CPoint*pPoint1=newCPoint;pPoint1->SetXY(6,7); //设置pPoint1所指对象的属性值

CPoint&refPoint=MyPoint1;x=refPoint.GetX();}三种调用方式对象的内存映像共102页第36页5.3.2对象的创建及初始化2.成员函数中对象成员的引用CBook*CBook::GetBookPtr(){……returnthis;}CBook&CBook::GetBookRef(){……return*this;}this指针并不常用,通常用于定义返回指向隐式对象指针或引用的成员函数。例如,在CBook类中添加需要返回指当前函数所属对象的引用或指向该对象的指针,可以按如下方式定义:voidCPoint::SetXY(intx,inty){this->m_x=x;this->m_y=y;}成员函数所引用的数据成员或函数成员并未指明是哪个对象的成员隐式调用显式调用共102页第37页3.对象创建与构造函数5.3.2对象的创建及初始化构造函数的名字与类的名字相同,而且构造函数没有返回值,即使是void类型也是非法的,只要满足了这两个条件,原则上可以定义任何形式的构造函数,因此构造函数是可以重载的。例如,为CPoint类添加构造函数:CPoint::CPoint(){m_x=0;m_y=0;}CPoint::CPoint(intx,inty){m_x=x;m_y=y;}CPoint::CPoint(constCPoint&pt){m_x=pt.m_x;m_y=pt.m_y;}CPointmPt1; //调用CPoint::CPoint()CPointmPt2(2,3); //调用CPoint::CPoint(intx,inty)CPoint*pPt1=newCPoint(4,5); //调用CPoint::CPoint(intx,inty)CPoint*pPt=newCPoint(mPt2); //调用CPoint::CPoint(CPoint&pt)在创建对象时,构造函数被自动调用,究竟调用多个构造函数中的哪一个要根据创建对象时所提供的初始化参数,采用重载函数的判断机制判断。例如下面的对象声明语句:CPoint::CPoint(constCPointpt)CPoint::CPoint(constCPoint*pt)CPoint::CPoint(CPointpt)共102页第38页4.对象的消亡与析构函数5.3.2对象的创建及初始化当一个对象消亡时会自动调用相应的析构函数进行一系列的“善后”工作,如:释放曾经申请的内存空间等。~ClassName(){}enumSEX{male,female,unknow};classCStudent{private:char* m_pczName;int m_nAge;SEX m_sSex;public:CStudent(char*pName,intnAge,SEXs);CStudent(char*pName);~CStudent();};CStudent::CStudent(char*pName){cout<<"OBJECTCREATE:"<<pName<<endl;m_pczName=newchar[strlen(pName)+1];if(m_pczName!=0)strcpy(m_pczName,pName);m_nAge=-1; //-1表示尚未初始化该属性

m_sSex=unknow;}CStudent::CStudent(char*pName,intnAge,SEXs){cout<<"OBJECTCREATE:"<<pName<<endl;m_pczName=newchar[strlen(pName)+1];if(m_pczName!=0)strcpy(m_pczName,pName);

m_nAge=nAge;m_sSex=s;}CStudent::~CStudent(){cout<<"OBJECTDELETE:"<<m_pczName<<endl;delete[]m_pczName;}voidmain(){CStudents1("John",10,male);CStudent*ps=newCStudent("Jane",10,female);deleteps;}共102页第39页5.关于拷贝构造函数5.3.2对象的创建及初始化ClassName(ClassName&srcObj);缺省拷贝构造函数,其功能是将形参对象的属性值直接赋值给新创建对象的相应属性,使得两个对象的对应属性的值相同。当类中具有指针类属性时,将出现运行错误,如将上例中主函数改为(运行,原因):voidmain(){CStudents1("John",10,male);CStudents2(s1);}classCStudent{private:char* m_pczName;int m_nAge;SEX m_sSex;public:CStudent(char*pName,intnAge,SEXs);CStudent(char*pName);

CStudent(constCStudent&srcStudent){m_pczName=newchar[strlen(srcStudent.m_pczName)+1];strcpy(m_pczName,srcStudent.m_pczName);}~CStudent();};共102页第40页对象属性值的变化(对象间的赋值)5.3.2对象的创建及初始化在对象间可以使用赋值符

CPointPt1,Pt2; Pt1.SetXY(2,3); Pt2=Pt1;由于系统会给出赋值符的缺省定义,所以Pt2和Pt1对应的属性相等class<ClassName>{……<ClassName>&operator=(<TYPE>arg);

//返回值类型可以为ClassName、void及其它任何类型

……};<ClassName>&<ClassName>::operator=(TYPEarg)

//返回值类型与原型相同{……}共102页第41页5.3.3消息传递与操作调用操作调用方式与消息传递classLine{private:CPointm_cpStartPoint;CPointm_cpEndPoint;public:voidSetLine(CPoint&Start,CPoint&End){m_cpStartPoint.SetXY(Start.GetX(),Start.GetY());m_cpEndPoint.SetXY(End.GetX(),End.GetY());}};classCPoint{private:intm_x;intm_y;public:void SetXY(intx,inty){m_x=x;m_y=y;}intGetX(){returnm_x;}intGetY(){returnm_y;}};共102页第42页5.3.4继承1.单一继承C++提供下述常见语法格式:

class<DerivedClassName>:<AccessSpecifier><BaseClassName>{……};

矩形长宽位置求面积求周长求位置正方形求面积求周长求位置边长classCRectangle//矩形类{public:CPointm_cpLocation;//图形所在位置

intm_nWidth; //图形的宽度

intm_nHeight; //图形的高度

CRectangle(intnX,intnY,intnWidth,intnHeight);intGetArea(); //求面积

intGetPerimeter(); //求周长

CPoint&GetPosition();//返回图形位置};共102页第43页CRectangle::CRectangle(intnX,intnY,intnW,intnH):m_cpLocation(nX,nY){ m_nWidth=nW; m_nHeight=nH;}intCRectangle::GetArea(){returnm_nWidth*m_nHeight;}intCRectangle::GetPerimeter(){returnm_nWidth+m_nWidth+m_nHeight+m_nHeight;}CPoint&CRectangle::GetPosition(){returnthis->m_cpLocation;}5.3.4继承1.单一继承对象属性成员的初始化:ClassName::ClassName(ArgList0):ObjectName(ArgList1){……}共102页第44页classCSquare:publicCRectangle//正方形类,派生自矩形类{intm_nEdge;public:CSquare(intnX,intnY,intnEdge);intGetEdge();//返回边长};CSquare::CSquare(intnX,intnY,intnEdge):CRectangle(nX,nY,nEdge,nEdge){m_nEdge=nEdge;}intCSquare::GetEdge(){returnm_nEdge;}5.3.4继承1.单一继承继承中的构造函数实现:ClassName::ClassName(ArgList0):BaseClassName(ArgList1){……}共102页第45页voidmain(){CRectangler(1,1,2,3);CSquares(0,0,2);cout<<r.GetArea()<<endl<<s.GetArea()<<endl;}5.3.4继承1.单一继承共102页第46页5.3.4继承2.基类成员访问控制有两个因素同时控制着派生类对基类成员的访问权限,这两个因素就是基类类体中类成员的访问说明符,及派生类的派生方式。下表总结了这两个因素对基类成员访问权限的影响规律,从表可以看到,在任何派生方式下,基类的私有成员都是派生类不可访问成员;在保护派生情况下,除私有成员外均被派生类以保护成员方式所继承;公有派生时不改变基类公有和保护成员的访问权限基类成员在派生类中的访问权限 成类员派生方式privateprotectedpublicprivate不可访问私有私有protected不可访问保护保护public不可访问保护公有共102页第47页5.3.4继承3.多重继承C++还提供了另一种复杂的继承方式,允许从多个基类派生一个子类,即多重继承。一般形式为:class<ClassName0> : <AccessSpecifier1><ClassName1>, <AccessSpecifier2><ClassName2>, …, <AccessSpecifiern><ClassNamen>{……};<ClassName0>::<ClassName0>(ArgList0):<ClassName1>(ArgList1),…,<ClassNamen>(ArgListn){……}共102页第48页WNDSTRUCTCWindowTreeCScreenObjectCEditTextCWnd5.3.4继承3.多重继承#include"iostream.h"#include"stdlib.h"#include"string.h"classCWnd;//引用性说明#defineMAXTEXTBUFFER0xffffclassCPoint{private:intm_x;intm_y;public:CPoint(intx=0,inty=0){m_x=x;m_y=y;}intGetX(){returnm_x;}intGetY(){returnm_y;}};共102页第49页classWNDSTRUCT{//本对象中含有窗口公共数据

protected:char*m_pczWndName; //窗口名字

//下述变量表示窗口左上角和右下角的坐标

CPointm_cpTopLeft;CPointm_cpBottomRight;

//下述三个量用于建立窗口系统的树结构

CWnd*m_pParentWindow; //指向本窗口的父窗口

CWnd**m_pChildFirst; //CWnd的指针数组,放着本窗口的子窗口

CWnd**m_pSiblingFirst; //指向本窗口的兄弟窗口

char*m_pEditTextBuffer; //指向窗口编辑区文本缓冲区

public:WNDSTRUCT(constWNDSTRUCT&rWndArch){m_pczWndName=newchar[strlen(rWndArch.m_pczWndName)+1];if(m_pczWndName==0){cout<<"Noenoughspace!"<<endl;exit(0);}strcpy(m_pczWndName,rWndArch.m_pczWndName);}~WNDSTRUCT(){delete[]m_pczWndName;}};共102页第50页classCScreenObject:virtualprivateWNDSTRUCT{public:voidMoveToWindow(constCPoint&cpWndPos,intnWidth,intnHeight){HideWindow();m_cpTopLeft=cpWndPos;m_cpBottomRight=CPoint(m_cpTopLeft.GetX()+nWidth,m_cpBottomRight.GetY()+nHeight);RedrawWindow();}~CScreenObject(){delete[]m_pczWndName;}

voidHideWindow(){/*隐藏当前窗口*/}

voidRedrawWindow(){/*绘制并显示当前窗口*/}};共102页第51页classCEditText:virtualprivateWNDSTRUCT{public:CEditText(WNDSTRUCT&rWndArch):WNDSTRUCT(rWndArch){m_pEditTextBuffer=newchar[MAXTEXTBUFFER+1];if(m_pEditTextBuffer==0){cout<<"Noenoughspace";exit(1);}memset(m_pEditTextBuffer,'\0',MAXTEXTBUFFER+1);}~CEditText(){delete[]m_pEditTextBuffer;}voidTextCut(intnStart,intnEnd){char*TempStr=newchar[MAXTEXTBUFFER-nEnd];memset(m_pEditTextBuffer+nEnd,'\0',MAXTEXTBUFFER-nEnd);memcpy(m_pEditTextBuffer+nStart,TempStr,MAXTEXTBUFFER-nEnd);delete[]TempStr;

//此处应该调用适当函数重新绘制编辑区显示内容

}

/*TextPaste(),TextCopy()等函数*/};共102页第52页classCWindowTree:virtualprivateWNDSTRUCT{public:CWindowTree(WNDSTRUCT&rWndArch):WNDSTRUCT(rWndArch){}voidAddChild(CWnd*pChild){while(*m_pChildFirst!=0)++m_pChildFirst;*m_pChildFirst=pChild;}

/*其它关于窗口树的操作*/};classCWnd:publicCWindowTree,publicCEditText,publicCScreenObject{…};共102页第53页5.3.4继承3.多重继承(二义性)classCBase1{public:voidMyFunc(){cout<<"ThisisCBase1'sMyFunc"<<endl;}};classCBase2{public:voidMyFunc(){cout<<"ThisisCBase2'sMyFunc"<<endl;}};classCDerived:publicCBase1,publicCBase2{public:voidfunc(){MyFunc();}//错误!两义性!};voidmain(){CDerivedobj;obj.func();}classCDerived:publicCBase1,publicCBase2{public:voidfunc(){CBase1::MyFunc();//调用CBase1类的成员函数MyFunc()CBase2::MyFunc();//调用CBase2类的成员函数MyFunc()}};CBase2Func()CBase1MyFunc()CBase2MyFunc()共102页第54页5.3.4继承3.多重继承(派生类对象内存映像)classCBase{public:intb0;CBase(){b0=0x01;}};classCBase1:publicCBase{public:intb1;CBase1(){b1=0x11;}};classCBase2:publicCBase{public:intb2;CBase2(){b2=0x12;}};classCDerived:publicCBase1,publicCBase2{public:intb;CDerived(){b=0x21;}};voidmain(){CDerivedobj;}CBaseCBase1CBase2CBase2共102页第55页classCBase{public:intb;};classCBase1:publicCBase{};classCBase2:publicCBase{};classCDerived:publicCBase1,publicCBase2{public:intfunc();};CDerivedobj;obj.b; //错,二义性obj.CBase::b;

//错,二义性obj.CBase1::b;

//使用从CBase1来的bobj.CBase2::b;//使用从CBase2来的bclassCBase{public:intb0;CBase(){b0=0x01;}};classCBase1:virtualpublicCBase{public:intb1;CBase1(){b1=0x11;}};classCBase2:virtualpublicCBase{public:intb2;CBase2(){b2=0x12;}};classCDerived:publicCBase1,publicCBase2{public:intb;CDerived(){b=0x21;}};voidmain(){CDerivedobj;}5.3.4继承3.多重继承(虚基类)共102页第56页共102页第57页实现单向关联:

用指针可以方便地实现单向关联。如果关联的重数是一元的,则实现关联的指针是一个简单指针;如果重数是多元的,则需要用一个指针集合实现关联。

5.3.5关联的实现共102页第58页图5.4用指针实现单向关联(a)关联;(b)实现5.3.5关联的实现共102页第59页图5.5用指针集合实现关联(a)关联;(b)实现5.3.5关联的实现共102页第60页实现双向关联:

许多关联都需要双向遍历,当然,两个方向遍历的频度往往并不相同。实现双向关联有下列三种方法。

只用属性实现一个方向的关联,当需要反向遍历时就执行一次正向查找。

两个方向的关联都用属性实现。如图5.5

用独立的关联对象实现双向关联。如图5.65.3.5关联的实现共102页第61页图5.6用对象实现关联5.3.5关联的实现共102页第62页公司名称:char*m_pName老板:CPersonboss............boss结婚丈夫妻子人姓名:char*m_pName年龄:intm_nAge............工作单位由...掌管0..1老板薪金基本薪酬:intnBasic生活补助:intnSubsidy............为...工作**雇佣5.3.5关联的实现classCCompany{private:char*m_pName;//按图中要求

CPerson*boss;//因为图中标出老板可有可无,所以用指针表示

CPerson*m_Employee[20]//公司员工最多20};classCPerson{private:char*m_pName;intm_nAge;CCompany*comp;//comp为一个CCompany的数组,因为可为多个公司工作

CSalary*salary;//salary为一个CSalary数组,与每个comp相对应

CPeron*consort;//按图中的关系添加了这一个属性标明配偶

intsex; //为标明配偶为男女,所以引入本人的性别};classCSalary{//只要单向关系即可,所以没有引入标明工资所有者的属性

private:intnBasic;intnSubsidy;};共102页第63页5.3.6聚集关系的实现classCButton{

…CButton(){……}

…};classCIcon{

…CIcon(){……}

…};classCMessageWindow{private:CButtonm_ButtonOK;CButtonm_ButtonCANCEL;CIconm_Icon;

…public:CMessageWindow():m_ButtonOK(""),m_ButtonCANCEL(""),m_Icon(""){…}

…};消息窗口按钮图标菜单确定0..1帮助0..1消息10..1文件0..1编辑0..1消息窗口按钮确定0..1图标消息10..1菜单文件0..1编辑0..1帮助0..11.复合聚合的实现共102页第64页小组成员535班级成员组号:intm_nGroupID学生:CStudent*m_pStudentsCGroup设置学生:SetStudent(CStudent*)构造空组nID:CGroup(intnID)班号:intm_nClassID学生:CStudent*m_pStudentsCClass设置学生:SetStudent(CStudent*)构造空班nID:CClass(intnID)CStudent5.3.6聚集关系的实现2.共享聚合的实现classCStudent{CStudent(constchar*pStudentName){…}…};共102页第65页classCGroup{private:CStudent**m_pStudents;intm_nGroupID;intm_nstuNum;…public:voidSetStudent(CStudent*pStudents){if(m_nstuNum>=5){cout<<“小组成员已满”;return;}m_pStudent[m_nstuNum++]=pStudent;}

CGroup(intnID){m_nGroupID=nID;m_pStudents=new(Cstudnet*)[5];//小组由5名学生组成

m_nstuNum=0;…}…};共102页第66页classCClass{private:CStudent**m_pStudents;intm_nClassID;intm_nstuNum;…public:CClass(intnID){m_nClassID=nID;m_pStudents=new(Cstudent*)[35];//班级由35名学生组成

m_nstuNum=0;…}CStudent*GetStudent(){returnm_pStudents;}voidSetStudent(CStudent*pStudents){m_pStudent[m_nstuNum++]=pStudent;}……};共102页第67页voidmain(){CStudenttheWhole[100]={CStudent("Marry"),…,CStudent("Tom")};CClassMyClass3(3);

//成立班级,但具体由哪些学生组成尚未确定

MyClass3.SetStudent((theWhole+70));

//将学校学生名册中第71位学生加入到MyClass3班

CGroupGroup6(6);

Group6.SetStudent((MyClass3.GetStudent()+25));

//将MyClass3班的学生名册中第26名学生加入第6学习小组

…}共102页第68页5.3.7多态性与虚函数多态性(Polymorphism)C++支持两种多态性:编译时的多态性(静态)通过重载来实现运行时的多态性(动态)通过虚函数来实现共102页第69页5.3.7多态性与虚函数classPoint{private:intx,y;public:Point(){x=0;y=0;}Point(intx_pos,inty_pos){x=x_pos;y=y_pos;}Point(constPoint&p){x=p.x;y=p.y;}intgetx(){returnx;}intgety(){returny;}};enumColorType{White,Black,Red,Green,Blue,Yellow,Magenta,Cyan};ShapeLineRectangleCircleSquare绘图程序中多态性的应用共102页第70页classShape{private:ColorTypecolor;public:Shape(ColorTypec){color=c;}virtualvoiddraw(){cout<<“drawnotoverridden”<<endl;exit(1);}};classLine:publicShape{private:PointStart,End;public:Line(Points,Pointe,ColorTypec):Shape(c),Start(s),End(e){}virtualvoiddraw();};共102页第71页classRectangle:publicShape{private:PointupperLeft,lowerRight;public:Rectangle(Pointul,Pointlr,ColorTypec):Shape(c),upperLeft(up),lowerRight(lr){}virtualvoiddraw();};

classCircle:publicShape{private:Pointcenter;intradius;public:Circle(Pointctr,intr,ColorTypec):Shape(c),center(ctr){radius=r;}virtualvoiddraw();};共102页第72页classSquare:publicRectangle{public:Square(Pointul,intl,ColorTypec):Rectangle(ul,Point(ul.getx()+l,ul.gety()+l),c){}};

classPicture{private:Shape*s[6];public:Picture(Shape*s1,Shape*s2,Shape*s3,Shape*s4,Shape*s5,Shape*s6){s[0]=s1;s[1]=s2;s[2]=s3;

温馨提示

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

评论

0/150

提交评论