《面向对象程序设计 ch6.ppt》由会员分享,可在线阅读,更多相关《面向对象程序设计 ch6.ppt(36页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、第第6 6章面向对象编程实例章面向对象编程实例本章设计两个程序:求解一元二次方程的根和出圈游戏。本章设计两个程序:求解一元二次方程的根和出圈游戏。通过这两个程序,目的是练习如何使用面向对象的思想考通过这两个程序,目的是练习如何使用面向对象的思想考虑问题,如何首先抽象出求解问题的类,然后构造出一个虑问题,如何首先抽象出求解问题的类,然后构造出一个对象,让这个对象来解决实际问题。对象,让这个对象来解决实际问题。主要内容主要内容6.1 求解一元二次方程求解一元二次方程 6.1.1 设计代表方程的类设计代表方程的类 6.1.2 设计成员函数设计成员函数 6.1.2 设计成员函数设计成员函数6.2 出圈
2、游戏出圈游戏 6.2.1 设计思想设计思想 6.2.2 设计头文件设计头文件 6.2.3 实现实现SeqList.cpp文件文件 6.2.4 文件文件count.cpp 6.2.5 程序运行示范程序运行示范 6.2.6 组建工程组建工程 6.1 6.1 求解一元二次方程求解一元二次方程首先要从解一元二次方程出发,抽象一个代表一元二次方首先要从解一元二次方程出发,抽象一个代表一元二次方程的类。为了使用这个类,必需根据要解决的问题,为这程的类。为了使用这个类,必需根据要解决的问题,为这个类设计合适的数据成员和成员函数。个类设计合适的数据成员和成员函数。6.1.1 6.1.1 设计代表方程的类设计代
3、表方程的类因为目的是为了编制一个求方程因为目的是为了编制一个求方程ax2+bx+c=0的根的程的根的程序,所以首先要为这个类起个名字。假设这个类的名序,所以首先要为这个类起个名字。假设这个类的名字为字为FindRoot,至少需要将方程的系数作为至少需要将方程的系数作为FindRoot类的属性。可以将系数设计成类的属性。可以将系数设计成float型。型。为了方便,除了将方程系数设为属性之外,还将方程为了方便,除了将方程系数设为属性之外,还将方程的根的根x1和和x2,以及用来作为判定条件的以及用来作为判定条件的d(d=b*b-4*a*c),均设计成类的属性,并且将方程的两个根设均设计成类的属性,并
4、且将方程的两个根设为为double型,将型,将d设为设为float型。型。成员函数成员函数Find用来求方程的根,用来求方程的根,Display函数则用来输函数则用来输出结果。因为它们都需要用到属性出结果。因为它们都需要用到属性d,所以可以在构所以可以在构造函数中求出造函数中求出d的值,其他成员函数则可以直接使用的值,其他成员函数则可以直接使用这个属性,不必再去计算这个属性,不必再去计算d的值。的值。图图6.1是其类图。假设一个对象为是其类图。假设一个对象为obj,图图6.2是一个典型的是一个典型的obj的对象图,图中表明该方程为的对象图,图中表明该方程为x2-3x+2=0,d=1,x1=2,
5、x2=1。求求d需要使用库函数需要使用库函数sqrt,sqrt在头文件在头文件math.h中定义,只中定义,只要包含它既可。要包含它既可。FindRoota:floatb:floatc:floatd:float x1:double x2:doubleFindRoot:FindRootFind:void Display:voidobj:FindRoota=1b=-3c=2d=1x1=2x2=1FindRootFindDisplay图图6.1类图示意图类图示意图 图图6.2 obj对象图对象图6.1.2 6.1.2 设计成员函数设计成员函数1.1.设计构造函数设计构造函数FindRoot:Find
6、Root(float x,float y,float z)a=x;b=y;c=z;d=b*b-4*a*c;2.设计求根成员函数设计求根成员函数Find可以根据可以根据d大于、等于或小于零来决定求解方法。大于、等于或小于零来决定求解方法。if(d 0)/有两个不相等的实数解有两个不相等的实数解 else if(d=0)/有两个相等的实数解有两个相等的实数解 else /有两个不相等的虚数解有两个不相等的虚数解 一旦满足条件,应该马上退出程序。程序中使用一旦满足条件,应该马上退出程序。程序中使用“return;”语句实现。语句实现。void FindRoot:Find()if(d 0)x1=(-b
7、+sqrt(d)/(2*a);x2=(-b-sqrt(d)/(2*a);return;else if(d=0)x1=x2=(-b)/(2*a);return;else x1=(-b)/(2*a);x2=sqrt(-d)/(2*a);3.3.输出结果成员函数输出结果成员函数DisplayDisplay也根据也根据d d的情况显示不同结果,并使用的情况显示不同结果,并使用“return;return;”语句直语句直接退出。接退出。void FindRoot:Display()if(d 0)coutX1=x1nX2=x2endl;return;else if(d=0)coutx1=x2=x1endl
8、;return;else coutX1=x1+x2iendl;coutX2=x1-x2iendl;6.1.3 6.1.3 编程实现编程实现1.1.设计工程和文件设计工程和文件具体实现方法如下:具体实现方法如下:设计设计一个名为一个名为equation的工程。的工程。为工程设计为工程设计一个头文件一个头文件equation.h,声明声明class FindRoot 类并包含需要的头文件。类并包含需要的头文件。为工程设计为工程设计equation.cpp文件,在这个文件中实现文件,在这个文件中实现 FindRoot类。类。在在equation.cpp文件文件中包含头文件中包含头文件equation
9、.h。设计主函数对方程求解。设计主函数对方程求解。主函数求解思想如下:主函数求解思想如下:首先使用首先使用接受的系数创建该类的一个对象接受的系数创建该类的一个对象obj。即:即::FindRoot obj(a,b,c,);构造函数构造函数自动计算自动计算d值。值。对象对象obj调用调用成员函数成员函数Find求出方程的根。即:求出方程的根。即:obj.Find();将求出的根存入属性中。将求出的根存入属性中。对象对象obj调用调用成员函数成员函数Display输出自己的根。即:输出自己的根。即:obj.Display();下面给出完整的程序。下面给出完整的程序。2.头文件头文件/equatio
10、n.h#if!defined(EQUATION_H)#define EQUATION_H#include#include using namespace std;/*/*声明声明FindRoot类类 */*class FindRoot private:float a,b,c,d;double x1,x2;public:FindRoot(float x,float y,float z);void Find();void Display();#endif3.3.实现类实现类在在equation.cpp文件中实现类的成员函数。文件中实现类的成员函数。/equation.cpp#include equ
11、ation.h/*/*实现实现 FindRoot类类 */*/构造函数构造函数FindRoot:FindRoot(float x,float y,float z)a=x;b=y;c=z;d=b*b-4*a*c;/实现成员函数实现成员函数Find/实现成员函数实现成员函数Findvoid FindRoot:Find()if(d 0)x1=(-b+sqrt(d)/(2*a);x2=(-b-sqrt(d)/(2*a);return;else if(d=0)x1=x2=(-b)/(2*a);return;else x1=(-b)/(2*a);x2=sqrt(-d)/(2*a);/实现成员函数实现成员函
12、数Displayvoid FindRoot:Display()if(d 0)coutX1=x1nX2=x2endl;return;else if(d=0)coutx1=x2=x1endl;return;else coutX1=x1+x2iendl;coutX2=x1-x2iendl;4.4.主函数主函数在在equation.cpp文件中编写主函数。为了解方程,需要在文件中编写主函数。为了解方程,需要在主函数中准备一元二次方程的系数主函数中准备一元二次方程的系数a、b、c,然后使用然后使用这个系数作为构造函数的参数创建一个对象这个系数作为构造函数的参数创建一个对象obj。obj已经已经具有解方程
13、的必要属性:具有解方程的必要属性:a、b、c、d。obj使用自己的成使用自己的成员函数员函数Find求解,利用成员函数求解,利用成员函数Display输出计算结果。输出计算结果。为了能连续求解,使用为了能连续求解,使用for循环语句。如果要停止计算,循环语句。如果要停止计算,使系数使系数a=0即可。即可。void main()float a,b,c;cout“这是一个求方程这是一个求方程ax2+bx+c=0的根的程序。的根的程序。”endl;for(;)couta;if(a=0)/系数系数a为零,则退出计算程序为零,则退出计算程序 getchar();/为了消除回车的影响为了消除回车的影响 r
14、eturn;coutb;coutc;FindRoot obj(a,b,c);/建立对象建立对象obj obj.Find();/求解求解 obj.Display();/输出计算结果输出计算结果 6.1.4 6.1.4 运行示范运行示范程序编译通过,运行示范如下:程序编译通过,运行示范如下:这是一个求方程这是一个求方程ax2+bx+c=0ax2+bx+c=0的根的程序。的根的程序。输入方程系数输入方程系数a:1a:1输入方程系数输入方程系数b:-2b:-2输入方程系数输入方程系数c:1c:1x1=x2=1x1=x2=1输入方程系数输入方程系数a:1a:1输入方程系数输入方程系数b:-3b:-3输入
15、方程系数输入方程系数c:2c:2X1=2X1=2X2=1X2=1输入方程系数输入方程系数a:1a:1输入方程系数输入方程系数b:3b:3输入方程系数输入方程系数c:5c:5X1=-1.5+1.65831iX1=-1.5+1.65831iX2=-1.5-1.65831iX2=-1.5-1.65831i输入方程系数输入方程系数a:0a:06.2 6.2 出圈游戏出圈游戏 这其实就是约瑟夫环游戏,只是作了一点修改而这其实就是约瑟夫环游戏,只是作了一点修改而已。这里假设有人数为已。这里假设有人数为n n个人的一个小组,他们按顺个人的一个小组,他们按顺时针方向围坐一圈。时针方向围坐一圈。一开始任选一个正
16、整数作为报数上限值一开始任选一个正整数作为报数上限值m m,从第一从第一个人开始按顺时针方向自个人开始按顺时针方向自1 1开始顺序报数,报到开始顺序报数,报到m m时停时停止报数。报数止报数。报数m m的人出列,然后从他原来所在的,顺的人出列,然后从他原来所在的,顺时针方向的下一个人开始重新从时针方向的下一个人开始重新从1 1报数,报到报数,报到m m时停止时停止报数并出列。报数并出列。如此下去,直至所有人全部出列为止。要求按他如此下去,直至所有人全部出列为止。要求按他们出列的顺序输出他们的名字。们出列的顺序输出他们的名字。6.2.1 6.2.1 设计思想设计思想 本程序的设计思想与解方程的设
17、计思想不一样。本本程序的设计思想与解方程的设计思想不一样。本程序虽然使用对象,但不是使用一个对象来解题,而程序虽然使用对象,但不是使用一个对象来解题,而是建立一个对象数组,然后用对象数组作为一个函数是建立一个对象数组,然后用对象数组作为一个函数的参数,从而使用这个函数来求解,目的是练习设计的参数,从而使用这个函数来求解,目的是练习设计使用类对象作为参数的函数。使用类对象作为参数的函数。设计一个类,该类有两个属性,一个是整数存放数字,设计一个类,该类有两个属性,一个是整数存放数字,用来作为报数的位置。一个是字符串,用来存放相应用来作为报数的位置。一个是字符串,用来存放相应的名字。的名字。使用这个
18、类构造一个类的对象数组,则可以通过对象使用这个类构造一个类的对象数组,则可以通过对象数组的下标,将位置和名字对应起来。数组的下标,将位置和名字对应起来。要求建立一个工程,但使用要求建立一个工程,但使用3个文件编程。具体要求如下:个文件编程。具体要求如下:设计一个设计一个SepList工程。工程。设计一个设计一个SeqList.h文件,文件,在头文件中声明在头文件中声明SeqList.h类和类和Joseph函数。函数。在在SeqList.h文件文件中用内联函数实现中用内联函数实现SeqList类。类。在在SeqList.cpp文件文件中实现中实现Joseph函数。函数。在在count.cpp文件
19、中文件中编写主程序,使用类的数组来求解。编写主程序,使用类的数组来求解。6.2.2 6.2.2 设计头文件设计头文件对与对与SeqList类来说,要求使用名字,而在名字的字符串类来说,要求使用名字,而在名字的字符串中,允许存在空格。在声明的类中,同时定义的成员函数中,允许存在空格。在声明的类中,同时定义的成员函数就是默认的内联函数。另外,考虑到使用类的数组,所以就是默认的内联函数。另外,考虑到使用类的数组,所以不为它定义构造函数,而是用系统提供的默认无参数构造不为它定义构造函数,而是用系统提供的默认无参数构造函数。图函数。图6.3是是SeqList类类的类示意图。的类示意图。SeqList m
20、u:int name:char GetNum:int SetNum:void SetName:void DispName:void 图图6.3 类图示意图类图示意图注意注意Joseph函数声明要在类声明之后,否则编译函数声明要在类声明之后,否则编译会出错。会出错。完整的头文件如下:完整的头文件如下:/SeqList.h文件文件#if!defined(SEQLIST_H)#define SEQLIST_H#include using namespace std;/*/*声明声明SeqList类类 */*使用内联函数定义类使用内联函数定义类 */*class SeqListint num;char
21、 name10;public:int GetNum()return num;void DispName()coutname;void SetNum(int a)num=a;void SetName(char b)strcpy(name,b);void Joseph(SeqList,int);/声明函数原型声明函数原型#endif6.2.3 实现实现SeqList.cpp文件文件使用类的数组,其实就是利用顺序存储结构求解。在数组使用类的数组,其实就是利用顺序存储结构求解。在数组初始化后,调用函数初始化后,调用函数Joseph寻找出列人员。假设建立类的寻找出列人员。假设建立类的数组数组c,这是只能
22、为数组这是只能为数组c假设一个长度,实际的有效长度假设一个长度,实际的有效长度只有在给定的人数之后才能知道。它的算法思想如下:只有在给定的人数之后才能知道。它的算法思想如下:BEGIN初始化初始化 人数人数length 参加游戏人的名字参加游戏人的名字 计数器初值计数器初值 k从从1开始循环开始循环length次次 j计数器清零计数器清零 j循环循环(j间隔次数间隔次数m)计数计数i 如果如果i数到尾部,则返回到第一个位置,数到尾部,则返回到第一个位置,即重置即重置i等于等于0 如果该位置人员仍然在圈中,则如果该位置人员仍然在圈中,则j计数加计数加1endj/结束循环结束循环j 如果是最后一个
23、,结束循环,作特殊处理如果是最后一个,结束循环,作特殊处理 不是最后一个,输出出圈人的信息不是最后一个,输出出圈人的信息 标识该人员已出圈,开始新一轮循环标识该人员已出圈,开始新一轮循环 endk最后一个结束循环,输出他的信息。最后一个结束循环,输出他的信息。END判断是利用数据成员判断是利用数据成员num的值。将已经出圈的的值。将已经出圈的num标志标志为为0。下次数到他时,作为无效数据处理。输出使用数据。下次数到他时,作为无效数据处理。输出使用数据成员成员name。将这个函数设计成将这个函数设计成void型,使用型,使用数组作为参数,同时需要数组作为参数,同时需要将人数传给它。设计的的原型
24、为:将人数传给它。设计的的原型为:void Joseph(SeqList,int)完整的程序清单如下:完整的程序清单如下:/SeqList.cpp#include SeqList.hvoid Joseph(SeqList c,int length)int m;coutPlease input first interval m(mm;/初始报数值初始报数值 while(m20)coutm;coutPlease input code:endl;getchar();/输入参加游戏人的名字输入参加游戏人的名字 char s10;for(int i=0;ilength;i+)cout第第i+1个人的名字
25、个人的名字:;gets(s);ci.SetName(s);i=-1;int j,k;for(k=1;k=length;k+)j=0;while(jm)i+;if(i=length)/返回到第一个位置返回到第一个位置 i=0;if(ci.GetNum()!=0)j+;/若该人员在圈若该人员在圈 /中,则计数有效中,则计数有效if(k=length)break;ci.DispName();/输出出圈人的信息输出出圈人的信息cout,;ci.SetNum(0);/标识该人员已出圈标识该人员已出圈/break语句跳转至此语句跳转至此ci.DispName();coutendl;/输出最后出列的编号输出
26、最后出列的编号 6.2.4 文件文件count.cpp位置编号应该从位置编号应该从1开始,但开始,但C+的数组是从的数组是从0开始,所开始,所以以num的值比其所在数组的下标的值多的值比其所在数组的下标的值多1,这样做是为,这样做是为了直观。数组的大小一旦定义,就不能改变。了直观。数组的大小一旦定义,就不能改变。BEGIN 初始化初始化n和和length 定义数组定义数组 cn;初始化数组初始化数组c 调用调用Josep函数函数END本程序为本程序为Josep函数准备好参数之后,即调用该函数完成函数准备好参数之后,即调用该函数完成计算。计算。/count.cpp#include SeqList
27、.h“void main()const int n=30;int length=0;coutlength;SeqList cn;/建立对象数组建立对象数组 for(int i=0;ilength;i+)/初始化对象数组初始化对象数组 ci.SetNum(i+1);ci.SetName();Joseph(c,length);/将数组作为函数参数将数组作为函数参数6.2.6 6.2.6 组建工程组建工程 按按6.2.16.2.1的设计思想建的设计思想建立工程文件立工程文件SeqList,再再建立如下建立如下3个文件个文件:SeqList.h、SeqList.cpp和和count文件。文件。编写相应
28、的程序。编写相应的程序。图图6.46.4是工程的结构图。是工程的结构图。图图6.4 工程结构示意图工程结构示意图6.2.5 程序运行示范程序运行示范输入输入5 5个人,间隔为个人,间隔为1010。运行情况如下:。运行情况如下:please input the number of people:5Please input first interval m(m=20)10Please input code:第第1 1个人的名字个人的名字:李一明李一明第第2 2个人的名字个人的名字:王小二王小二第第3 3个人的名字个人的名字:张张 三三第第4 4个人的名字个人的名字:李李 四四第第5 5个人的名字个人的名字:王老五王老五王老五王老五,王小二王小二,张张 三三,李一明李一明,李李 四四