第一篇:华中科技大学c++第3次上机作业
华中科技大学
《计算机基础与程序设计(C++)》
实验报告
实验名称:第三次上机实验实验学时:4 姓名:学号:班级:电气
实验日期:2017/3/27
教师批阅签字:
一、实验目的
掌握三种循环语句的使用。学会使用continue 和break。掌握多重循环的设计。掌握常用算法的应用。
二、实验内容
1.在vc环境下编写下述程序代码,编译调试然后用不同的数据测试直至得到完全正确的结果。并解释出错原因。
#include
cout<<“输入一个正数:”;
cin>>a;
if(a<0)
cout< else; { x0=a/2; x1=(x0+a/x0)/2; while(abs(x1-x0)>=1e-5){ x0=x1; x1=(x0+a/x0)/2; } cout<< a<<“的平方根为:”< } return 0;语法错误: 1.最后缺少花括号。逻辑错误: 1.else后面有分号,导致花括号中的语句不受else限制。2.abs所提供的精度为整数 更改后的程序: #include cout<<“输入一个正数:”; cin>>a; if(a<0) cout< else { x0=a/2;x1=(x0+a/x0)/2; while(fabs(x1-x0)>=1e-5){ x0=x1; x1=(x0+a/x0)/2; } cout<< a<<“的平方根为:”< } return 0;} 2.下列程序的功能是:计算一对兔子,从出生后第3个月起每个月都生一对兔子。小兔子长到第3个月后每个月又生一对兔子,假设兔子不存在死亡问题,请问从第1个月到第20个月,每个月有多少对兔子?要求输出时按行列方式每行显示5个数据。如下图: 编译调试该程序看是否正确,不正确的话修改之直至完全满足要求。并解释出错原因。int main(){ int fib0=0,fib1=1,fib2;int n; } cout< 语法错误: 1.缺少头文件(iostream以及iomanip)以及命名空间。2.return0后的分号为中文分号。逻辑错误: 1.cout< #include int fib0=0,fib1=1,fib2;int n; cout< fib2=fib0+fib1; cout< fib0=fib1; fib1=fib2; if((n+1)%5==0)cout< } return 0;} 3. 编程任意输入一个三位数,判断其是否是水仙花数(水仙花数是指这个数等于个位,十位和百位的立方和。例如:153=13+53+33)要求: 程序原代码,及运行结果截图。(直接粘贴在此) #include cout<<“该整数为水仙花数”< cout<<“该整数不是水仙花数”< 解决本题的算法思路描述。 首先要解决的是如何取得个十百三位的数字,然后用if语句进行判断。调试过程的记载(包括出现的错误,以及修改过程)对十位和百位的数字进行提取的时候出现错误。 开始时: g=a%10;改正后:g=a%10; s=a%100;s=(a/10)%10;b=a%1000;b=a/100;4. 输出3到100以内的所有素数。(要求每行显示8个数) 提示:该题需要用到多重循环,外循环代表需要判断的数,从3到100,内循环判断该数是否是素数,参考教材的例4.9(判断一个数是否为素数)。 要求: 程序原代码,及运行结果截图。(直接粘贴在此) #include a=1; for(n=2;n { if(i%n==0) } { a=0; break; } } if(a==1) { cout< m=m+1; if(m%8==0) cout< } else ; } return 0; 解决本题的算法思路描述 运用双重循环语句进行,一个用来判断是否为素数,另外一个用来循环3-100.调试过程的记载(包括出现的错误,以及修改过程) a需要每次循环都赋值,最初放在循环外,导致只能输出3一个数字。花括号位置错误,导致格式不正确。 5. 连续输入n 个整数(n由键盘输入)统计其中正数、负数和零的个数。要求: 程序原代码,及运行结果截图。(直接粘贴在此) #include cin>>a; if(a==0) l++; else if(a>0) z++; else f++;} cout<<“统计的数据中正数、负数以及0的个数分别”< 解决本题的算法思路描述 首先判断输入数据的个数,然后运用for循环和if-else语句进行统计出现次数。调试过程的记载(包括出现的错误,以及修改过程)未出现错误,但是最开始的程序未进行相关提示。 6. 改写教材115 例18,规则为5局3胜制规则,其余条件不变。要求: 程序原代码,及运行结果截图。(直接粘贴在此) #include cout<<“请输入两个小孩的划拳值,1代表石头,2代表剪刀,3代表布。”< cin>>p1>>p2; switch(p1) { case 1:cout<<“石头”;break; } case 2:cout<<“剪刀”;break;case 3:cout<<“布”;break;} cout<<'t';switch(p2){ case 1:cout<<“石头”;break;case 2:cout<<“剪刀”;break;case 3:cout<<“布”;break;} cout<<'n';if(p1==p2) continue;if(p1==1&&p2==2||p1==2&&p2==3||p1==3&&p2==1) v1++;else v2++;} if(v1==3)cout<<“小孩1获胜”< 解决本题的算法思路描述 通过修改while的循环条件即可实现五局三胜制 只需要统计两个孩子的胜利次数,谁先到达三次即获胜 调试过程的记载(包括出现的错误,以及修改过程)由于为书中例题,只需简单修改即可完成,故未出现错误 7. 改写教材龟兔赛跑程序,要求在指定距离的条件下比赛,其余规则不变。要求: 程序原代码,及运行结果截图。(直接粘贴在此) #include int s,sw=0,st=0,station=0,sleep=0,run=0;cout<<“输入比赛距离:”;cin>>s;while(sw if(station==0) { run++; sw+=3; st+=9; if(run==10) { run=0; if(st>sw) station=1; else ; } else ; } else { sleep++;sw+=3;if(sleep==30){ station=0;sleep=0;} else;} } if(sw>st) cout<<“乌龟胜”< cout<<“兔子胜”< else cout<<“平局”< 解决本题的算法思路描述 1.以时间为循环的控制条件,计算两者走相同路程时谁的时间少,运用累计时间的算法,有一者到达指定路程就停止计时,然后比较两者的路程。2.对乌龟和兔子的行程进行累计,通过速度和时间来完成。 3.判断兔子是否在进行休息,用station来表示,0为运动1为睡觉。4.累计睡觉的时间,每到十分钟要重新从0开始计算。调试过程的记载(包括出现的错误,以及修改过程)赋值符号与判断相等的符号混淆。 8. 小王拿了50元钱准备去菜场买菜,已知黄瓜3元1斤,韭菜5元1斤,西红柿4元1斤,如何买这3样菜(每种菜都必须买),并且将50元花完,列出所有可能的买法。(只考虑整斤)要求: 程序原代码,及运行结果截图。(直接粘贴在此)#include for(j=1;j<=10;j++) { for(x=1;x<13;x++) { if(3*h+5*j+4*x==50) cout<<“黄瓜,韭菜,西红柿的数量分别为”< } } } return 0;} 解决本题的算法思路描述 利用多重循环,使用穷举法得出结果。 调试过程的记载(包括出现的错误,以及修改过程)For语句中;错写为,循环语句出错,更改了循环语句。 9. 编程将一个10进制整数转换成2进制整数。要求: 程序原代码,及运行结果截图。(直接粘贴在此) #include 解决本题的算法思路描述 十进制转为二进制的各个位数的数字用对2取余获得 然后用数组储存数字 最后倒序输出 调试过程的记载(包括出现的错误,以及修改过程)For语句中的j开始时定义错数值,应为i-1忘记减1 10. 编程将一个10进制定点小数转换成2进制定点小数。要求: 程序原代码,及运行结果截图。(直接粘贴在此) #include a=s*2; if(a>=1) s=a-1; else s=a; m++; cout< if(s==0) break;} cout< 解决本题的算法思路描述 小数点后的每一位数字用乘2循环求得,乘2后的小数用floor取整 调试过程的记载(包括出现的错误,以及修改过程)输入数据的类型出错。由int改为double 11. 编程要求从文件in.txt 中连续读入n个数(n由键盘输入),统计其中正数、负数和零的个数。(in.txt 是事先建好的一个文件存有若干数据,当输入的n值大于in.txt文件中的数据个数时给出相应的提示,判断文件中的数据是否读完使用eof()函数。eof()函数是判断是否到文件结尾,如果到文件结尾函数返回1,否则返回0,具体参考教材115页例4.17)要求: 程序原代码,及运行结果截图。(直接粘贴在此) #include in>>x; i++; if(x==0) l++; else if(x>0) z++; else f++;} m=l+z+f; if(n>m) {cout<<“数据数量小于所要统计的数量”< cout<<“统计的正数、负数和零数量分别为”< in.close(); return 0;} 解决本题的算法思路描述 运用读取文件的语句,用if语句累计三种数据的个数。调试过程的记载(包括出现的错误,以及修改过程) 逗号用的中文用了''标志出现错误。更改为英文的逗号正常了。 12.(选做)一位商人有一个40磅的砝码,由于跌落在地而碎成4块,后来称得每块碎片的重量都是整数,而且可以用这4块来称从1到40磅之间的任意整数磅的重物,问这4块砝码碎片各重多少? 提示:此题需要两次用到穷举法,第一次穷举是4个砝码的重量,分别用四个循环变量i, j, k, l来表示。第二次穷举是当i+j+k+l==40时,对重1磅到40磅共40种物品使用i, j, k, l四个称进行组合,设置一个计数器,组合出1个计数器加1,如果能组合出40个,就是我们要找的答案。 要求: 程序原代码,及运行结果截图。(直接粘贴在此) #include { int i,j,k,l,d1,d2,d3,d4,x,flag,s=0; cout<<“砝码分为”; for(i = 1;i < 41;i++) { for(j = i;j < 41;j++) { for(k = j;k < 41;k++) { if((l = 40-i-j-k)>=k) { s=0; for(x=1;x<41;x++) { flag=0; for(d1=1;d1>-2&&flag==0;d1--) { for(d2=1;d2>-2&&flag==0;d2--) { for(d3=1;d3>-2&&flag==0;d3--) { for(d4=1;d4>-2&&flag==0;d4--) { if(x == i*d1+j*d2+k*d3+l*d4) { flag = 1; s++; } } } } } if(s==40) { cout< } } } } } } return 0; } 解决本题的算法思路描述 首先找出所有组合,然后进行筛选。 调试过程的记载(包括出现的错误,以及修改过程)最终的输出语句所在位置一直不正确,通过调试解决。解决同一个x可能导致s多次累加的问题 解决存在重复的问题,即出现1.3.9.27和3.1.9.27等 三、对本次实验内容及方法、手段的改进建议,以及实验心得实验心得包括:1)哪些知识点已掌握 2)哪些知识点有困难 3)对讲课的建议 4)对没有掌握知识的补救建议 1) For语句循环,while以及do-while语句已经掌握。If-else语句、break、continue已经掌握。文件的读取与写入也已经能够运用。2) 对于龟兔赛跑等很复杂的问题掌握不够熟练 For语句很多次的叠加可能出错 3) 多进行程序上的演示,更容易理解。4) 多进行相关习题的训练掌握原理 重新阅读课本。 第二次上机实验报告 姓名:王小宁 班级: 学号: 031012 1234 第一题: 题目: 编写一个类,声明一个数据成员和一个静态数据成员,其构造函数初始化数据成员,并把静态数据成员加1,其析构函数把静态数据成员减1.(1)编写一个应用程序,创建该类的3个对象,然后显示其数据成员和静态数据成员,再析构每个对象,并显示它们对静态数据成员的影响。 (2)修改该类,增加静态成员函数并访问静态数据成员,并声明静态数据成员为保护成员。体会静态成员函数的使用,静态成员之间与非静态成员之间互访问题。 编程思想: 首先,定义一个类,其中含有两个类的私有变量,一个静态数据变量,定义构造函数,将初值赋给两个私有变量,并将静态数据变量加1,并显示.定义一个析构函数,并通过析构函数将静态成员变量减1.并显示。 修改以上的类,增加一个静态成员函数并通过静态成员函数来访问静态成员变量。在主函数中利用一个指向函数的指针指向这个静态成员函数,并通过这个指针来访问类中的静态数据。代码实现: 代码1: #include static int count; A(int a=0,int b=0) { X=a; Y=b; count++; cout<<“startcount=”< count--; cout<<“overcount=”< int GetX(){return X;} int GetY(){return Y;} private: int X,Y;};int A::count=0;int main(){ int *countp=&A::count;A z(2,3);cout<<“x=”< cout<<“x=”< 问题及心得: 在这次试验中,我理解了静态变量与普通变量之间的差异与联系。在实验过程中因未初静态变量始化而无法通过编译,并且注意到静态变量一定要在类外初始化。 题目2: 创建一个Person类,该类中有字符数组,表示姓名、街道地址、市、省和邮政编码。其功能有修改姓名、显示数据信息。要求其功能函数的原型放在类定义中,构造函数初始化每个成员,显示信息函数要求把对象中的完整信息打印出来。其中数据成员为保护的,函数为公有的。 编程思想: 创建一个PERSON类,定义姓名、街道地址、市、省和邮政编码分别为CHAR型的指针私有型变量。在定义公有型的构造函数,并在构造函数中申请动态内存来保存初始化的内容,并用相应的私有性的指针变量指向,再利用复制函数则指针中将会存放入输入内容。定义公有的析构函数释放动态申请的空间。定义一个公有的改变函数改变其中一个变量,方法与构造函数相似。 代码实现: #include private: char *name;char *street;char *pro;char *city;char *code; public: Person(char *aname,char *astreet,char *apro,char *acity,char *acode){ name=new char[strlen(aname)+1]; strcpy(name,aname); street=new char[strlen(astreet)+1]; strcpy(street,astreet); pro=new char[strlen(apro)+1]; strcpy(pro,apro); city=new char[strlen(acity)+1]; strcpy(city,acity); code=new char[strlen(acode)+1]; strcpy(code,acode); cout<<“constructor”< delete[] name; delete[] street; delete[] pro; delete[] city; delete[] code; cout<<“destructor”< delete[] name; name=new char[strlen(aname)+1]; strcpy(name,aname);} void show(){ cout<<“姓名:”< cout<<“街道地址:”< cout<<“省份:”< cout<<“城市:”< cout<<“邮政编码:”< 运行结果: 实验心得: 通过这个实验,我们学会了对类的私有的字符数组变量的初始化。利用指针动态分配空间。 C++上机实验报告 实验名称:实验 专业班级: 姓 名: 学 号: 实验日期: 11 实验 目录 1.实验目的 2.实验内容 3.程序代码 4.调试结果 5.实验心得 1.实验目的 实验10(1)进一步了解运算符重载的概念和使用方法;(2)掌握几种常用的运算符重载的方法;(3)了解转换构造函数的使用方法; (4)了解在Visual C++6.0环境下进行运算符重载要注意的问题。实验11(1)了解继承在面向对象程序设计中的重要作用;(2)进一步理解继承和派生的概念; (3)掌握通过继承派生出一个新的类的方法;(4)了解虚基类的作用和用法。 2.实验内容 实验10 事先编好程序,上机进行调试和运行程序,分析结果。(1)声明一个复数类Complex,重载运算符“+”,“-”,“*”,“/”,使之能用于复数的加,减,乘,除,运算符重载函数作为Complex类成员的函数。编程序,分别求两个复数之和,差,积和商。(2)声明一个复数类Complex,重载运算符“+”,使之能用于复数的加法运算。参加运算的两个运算量可以都是类对象,也可以其中有一个是整数,顺序任意。 运行程序,分别求两个复数之和,整数和复数之和,(3)有两个矩阵a和b,均为2行3列。求两个矩阵之和。重载运算符“+”,使之能用于两个矩阵相加 (4)声明一个Teacher(教师)类和一个Student(学生)类,二者有一部分数据成员是相同的,例如num(号码),name(名字),sex(性别)。编写程序,将一个Student对象(学生)转换为Teacher(教师)类,只将以上三个相同的数据成员移植过去。可以设想为:一位学生大学毕业了,留校担任教师,他原有的部分数据对现在的教师身份来说任然是有用的,应当保留并成为其教师的数据的一部分。 实验11 事先编写好程序,上机调试和运行程序,分析结果。 (1)将教材第11章例11.1的程序片段补充和改写成一个完整的、正确的程序,用公用继承方式。在程序中应当包括输入数据的函数,在程序运行时输入num,name,sex,age,addr的值,程序应输出以上5个数据的值。 (2)将教材第11章例11.3的程序修改、补充,写成一个完整、正确的程序,用保护继承方式。在程序中应包括输入数据的函数。(3)修改上面第(2)题的程序,改为用公用继承方式。上机调试程序,使之能够正确运行并得到正确的结果。 对这两种继承方式做比较分析,考虑在什么情况下二者不能互相替换。 (4)分别声明Teacher(教师)类和Cadre(干部)类,采用多 重继承方式由这两个类派生出新类Teacher-Cadre(教师兼干部)。要求: Ⅰ.在两个基类中都包含姓名、年龄、性别、地址、电话等数据成员。 Ⅱ.在Teacher类中还包含数据成员title(职称),在Cadre类中还包含数据成员post(职务)。在Teacher-Cadre类中还包含数据成员wages(工资)。 Ⅲ.在基类中的姓名、年龄、性别、地址、电话等数据成员用相同的名字,在引用这些数据成员时,指定作用域。Ⅴ.在类体中声明成员函数,在类外定义成员函数。 Ⅵ.在派生类Teacher-Cadre的成员函数show中调用Teacher类中的display函数,输出性命、年龄、性别、职称、地址、电话,然后再用cout语句输出职务与工资。 3.程序代码 实验10(1) #include Complex Complex::operator +(Complex &c2){Complex c;c.real=real+c2.real;c.imag=imag+c2.imag;return c;} Complex Complex::operator-(Complex &c2){Complex c;c.real=real-c2.real;c.imag=imag-c2.imag;return c;} Complex Complex::operator*(Complex &c2){Complex c;c.real=real*c2.real-imag*c2.imag;c.imag=imag*c2.real+real*c2.imag;return c;} Complex Complex::operator/(Complex &c2){Complex c;c.real=(real*c2.real+imag*c2.imag)/(c2.real*c2.real+c2.imag*c2.imag);c.imag=(imag*c2.real-real*c2.imag)/(c2.real*c2.real+c2.imag*c2.imag);return c;} void Complex::display(){cout<<“(”< (2) #include double real; double imag;}; Complex Complex::operator+(Complex &c){return Complex(real+c.real,imag+c.imag);} Complex Complex::operator+(int &i){return Complex(real+i,imag);} void Complex::display(){cout<<“(”< Complex operator+(int &i,Complex &c){return Complex(i+c.real,c.imag);} int main(){Complex c1(3,4),c2(5,-10),c3;int i=5;c3=c1+c2;cout<<“c1+c2=”;c3.display();c3=i+c1;cout<<“i+c1=”;c3.display();c3=c1+i;cout<<“c1+i=”;c3.display();return 0;}(3) #include int mat[2][3];}; Matrix::Matrix(){for(int i=0;i<2;i++)for(int j=0;j<3;j++)mat[i][j]=0;} Matrix operator+(Matrix &a,Matrix &b){Matrix c;for(int i=0;i<2;i++)for(int j=0;j<3;j++){c.mat[i][j]=a.mat[i][j]+b.mat[i][j];} return c;} void Matrix::input(){cout<<“input value of matrix:”< void Matrix::display(){for(int i=0;i<2;i++){for(int j=0;j<3;j++){cout< #include int num; char name[20]; char sex; float score;}; Student::Student(int n,char nam[],char s,float sco){num=n;strcpy(name,nam);sex=s;score=sco;} class Teacher {public: Teacher(){} Teacher(Student&);Teacher(int n,char nam[],char sex,float pay);void display();private: int num; char name[20]; char sex; float pay;}; Teacher::Teacher(int n,char nam[],char s,float p} {num=n;strcpy(name,nam);sex=s;pay=p;} Teaxher::Teacher(Student& stud){num=stud.get_num();strcpy(name,stud.get_name());sex=stud.get.sex();pay=1500;} void Teacher::display(){cout<<“num:”< #include void get_value() {cin>>num>>name>>sex;} void display() {cout<<”num:“< cout<<”sex:“< int num; char name[10];char sex;}; class Student1:public Student {public: void get_value_1(){get_value();cin>>age>>addr;} void display_1(){cout<<”age:“< char addr[30];}; int main(){Student1 stud1;stud1.get_value_1();stud1.display();stud1.display_1();return 0;}(2) #include void display();protected: int num; char name[10]; char sex;}; void Student::get_value(){cin>>num>>name>>sex;} void Student::display(){cout<<”num:“< class Student1:protected Student {public: void get_value_1();void display1();private: int age;char addr[30];}; void Student1::get_value_1(){get_value();cin>>age>>addr;} void Student1::display1(){cout<<”num:“< int main(){Student1 stud1;stud1.get_value_1();stud1.display1();return 0;}(3) #include int num; char name[10]; char sex;}; void Student::get_value(){cin>>num>>name>>sex;} void Student::display(){cout<<”num:“< class Student1:public Student {public: void get_value_1();void display1();private: int age; char addr[30];}; void Student1::get_value_1(){get_value();cin>>age>>addr;} void Student1::display1(){cout<<”num:“< int main(){Student1 stud1;stud1.get_value_1();stud1.display1();return 0;}(4) #include Teacher(int,char[],char);void display();private: int num;char name[20];char sex;}; Teacher::Teacher(int n,char nam[],char s){num=n;strcpy(name,nam);sex=s;} void Teacher::display(){cout<<”num:”< class BirthDate {public: BirthDate(int,int,int);void display();void change(int,int,int);private: int year;int month;int day;}; BirthDate::BirthDate(int y,int m,int d){year=y;month=m;day=d;} Void BithDate::display(){cout<<”birthday:”< void BirthDate::change(int y,int m,int d){year=y;month=m;day=d;} class Professor:public Teacher {public: Professor(int,char[],char,int,int,int,float);void display();void change(int,int,int);private: float area;BirthDate birthday;} Professor::Professor(int n,char name[20],char s,int y,int m,int d,float a): Teacher(n,name,s),birthday(y,m,d),area(a){} void Professor::display(){Teacher::display();birthday.display();cout<<”area:”< Int main(){Professor profl(3012,”Zhang”,’f’,1949,10,1,125.4);cout< 4.调试结果 实验10(1)c1+c2=(8,-6i)c1-c2=(-2,14i)c1*c2=(55,-10i)c1/c2=(-0.2,0.4)(2)c1+c2=(8,-6i)i+c1=(8,4i)c1+i=(8,4i) (3) input value of Matrix:11 22 33 44 55 66 input value of Matrix:12 13 14 15 16 17 Matrix a: 11 22 33 44 55 66 Matrix b: 12 13 14 15 16 17 Matrix c=Matrix a + Matrix b : 23 25 47 59 71 83 (4)student1 : num :20010 name:Wang sex:m score;89.5 Teacher2: num:20010 name:Wang sex:m pay:1500 实验11(1) 10101 Li M 20 Beijing num:10101 name:Li sex:M age:20 address:Beijing (2) 10101 Li M 20 Beijing num:10101 name:Li sex:M age:20 address:Beijing (3) 10101 Li M 20 Beijing num:10101 name:Li sex:M age:20 address:Beijing (4)The original data: num:3012 name:Zhang sex:f area:125.4 The new data: num:3012 name:Zhang sex:f birthday:6/1/1950 area:125.4 5.实验心得 这一次上机实验,除了了解到了运算符重载的概念和用法,掌握几种常用的运算符重载的方法,了解转换构造函数的使用方法,同时也能了解虚基类的用法,理解继承与派生的概念。 但是,最主要的,我觉得,是通过这一次的上机实验,我了解到,有的实验本身是没有程序错误的,但是,也会由于实验环境的影响而不能正常运行。换句话说,有的程序并不能在Visaul C++的环境下运行,而不是程序自身的问题。所以,对于没办法调试成功的程序,我们也不能一味的认为程序有错误,要学会理性的判断程序的对错,再下结论。 C++ 实验总结报告 研究课题:图形编辑器 学 校:华中科技大学 院 系: 班 级: 姓 名: 指导老师: 一、实验目的 1.熟悉C++的一些重要性质,利用封装、继承、虚函数和多态性等特性,通过实验学习如何对各类图元的属性和方法进行合理的封装 2.学习Microsoft的Visual C++编程工具 3.掌握MFC的相关知识 4.掌握基本的文件保存、读取以及操作封装技术 二、实验目的 设计一个简单的图形编辑器 三、实验所用仪器、设备 计算机:PentiumIII 800 以上 256M内存 操作系统:Windows 2000/XP 开发集成环境:Visual C++ 6.0 四、软件功能简介 (注:此软件是从网上下载得来) 该软件具有汉化的菜单界面(仿Windows自带画图软件),具有文件打开、编辑、保存等功能。编辑部分包括可以在编辑区域画直线、圆、矩形、曲线等矢量图形,可插入文字,可以修改线条的线型、颜色等基本属性。 五、部分代码分析 1.直线类代码: class CCreateLine : public CCommand { private: Position m_begin;// 直线的起点 Position m_end;// 直线的终点 public: CCreateLine();~CCreateLine(); int GetType();int OnLButtonDown(UINT nFlags, const Position& pos);int OnMouseMove(UINT nFlags, const Position& pos);int OnRButtonDown(UINT nFlags, const Position& pos); int Cancel();};学习C++我们最需要理解的就是它面向对象的设计思想。这种思想可以在类和对象上得到充分的体现。 类是面向对象程序设计的核心,它实际上是由用户定义的一种新的复杂数据类型。它是通过抽象数据类型ADT方法来实现的一种数据类型,将不同类型的数据和与这些数据相关的操作封装在一起形成一个集合体。因此,它具有更高的抽象性,实现了信息的隐藏和封装。 对象是某种类的一个实例,是类的具体体现。一个类可以有多个对象。 分析这一段代码,编程者将直线的起始点和终止点设置为私有成员,这样做就对整条直线实现了隐藏和保护,是面向对象中封装特性的一个具体体现;另外,此函数中还包含了构造函数与析构函数,构造函数完成对新对象的初始化工作,析构函数是构造函数的配对物,它实现与构造函数相反的功能。另外的几个成员函数名称形参返回值都与class Ccommand 中的几个公有函数相同,而在class Ccommand中,这几个函数都是虚函数,这是函数重载,也是多态性的具体体现。 由这段代码我们可以了解关于类和对象的一些知识,为我们进一步了解面向对象程序设计的思想精髓奠定了基础。 2.对构造函数和解析函数的分析 构造函数 CCreateLine::CCreateLine(): m_begin(0,0), m_end(0,0){ m_nStep = 0;// 初始化操作步为 0 } 此构造函数用初始化列表的方式对直线类的私有成员进行初始化,同时记下操作步m_nStep是直线类从指令类中继承来的成员,它在指令类中属于保护成员,在直线类中则成为私有成员。这是数据共享与数据保护两者兼顾时的一种处理方法。 析构函数 CCreateLine::~CCreateLine(){ } 此析构函数中没有任何操作语句,但它并非没有任何操作。在任何一个对象消失时都要调用本类的析构函数进行扫尾工作。在构造对象时,构造函数分配资源给程序,在对象作用结束后,这些资源的释放就要靠析构函数。当然析构函数中也是可以有语句的,当需要在对象消失之前执行某种操作时,可以把语句写在里边。 3.BOOL Cline::Pick(const Position&pos,const double pick_radius){ Position objPos=pos;BOX2D sourceBox,desBOX;GetBox(&sourceBox);desBox.min[0]=sourceBox.min[0]-pick_radius;desBox.min[1]=sourceBox.min[1]-pick_radius;desBox.max[0]=sourceBox.max[0]+pick_radius;desBox.max[1]=sourceBox.min[1]+pick_radius;if(!objPos.lslnBox(desBox))return FALSE;double angle=::GetAngleToXAxis(m_begin,m_end);Position dp =objPos-m_begin;Double dist = fabs(dp.x*cos(angle)+dp.y*sin(angle)-objPos.Distance(m_begin));if(dist<=pick_radius)return TRUE;return FALSE;} 在阅读此函数的源代码过程中,我感觉到对类创建的合理划分对整个程序具有着十分重要的意义。正如上段代码,它的前提是对类进行了合理的划分,只有在对类进行了合理的划分后,我们才能更加高效地处理对象。所以,我感觉到在学习面向对象程序设计时,应当尤为注意类的创建与划分。 六、个人学习体会 在学习C++以前,我认为C++只是在C语言的基础上的一种延伸,认为只要学过C语言,就可以用C语言的那种设计思想来学习C++、设计C++程序。正是由于抱了这种错误的思想,使我在一开始学习C++的时候遇到了很大的困难,我没有办法体会面向对象的设计思想,我在学习这门课的时候老是想着实现这个函数功能的具体过程,而没太注意对象分类的重要性。 随着课程学习的深入,我感觉到了利用类和对象、继承、封装等一系列知识可以把我们程序中很多繁杂、重复的部分省略掉,还可以解决一些利用面向过程的设计思想无法解决的问题,我自己也试着编写一些小的C++程序,当然在这个过程中遇到了很多困难,其中调试带来的困难让我无法忘记,在调试程序的同时,我也总结出来了一些调试的小技巧,让我在C语言课程设计中也受用匪浅。 在学习这门课的过程中,我感受到了自己亲自动手编程序、调程序的重要性,我们要熟悉C++的语法、体会调试的思想,最好的一个手段就是自己动手编程、调试,这会比我们一味的看书效果好得多。另外,我还感觉到一个好的程序编出来需要很多人的团结合作。我在检查自己编写的程序是否有BUG未被找出的时候,我会让我的同学作为一个程序使用者来找出未发现的BUG并提出改进意见,这让我们的工作更加高效。 很高兴能够了解到C++的神奇魅力和面向对象程序设计的独特思想,它为我今后的程序设计奠定了基础。感谢老师对我们的悉心教授! P179 5.9.2(11) 1.意图 保证一个类仅有一个实例,并提供一个访问它的全局访问点。 2.动机 对一些类来说,只有一个实例是很重要的。虽然系统中可以有许多打印机,但却只应该有一个打印假脱机(printer spooler),只应该有一个文件系统和一个窗口管理器。一个数字滤波器只能有一个A / D转换器。一个会计系统只能专用于一个公司。 我们怎么样才能保证一个类只有一个实例并且这个实例易于被访问呢?一个全局变量使得一个对象可以被访问,但它不能防止你实例化多个对象。一个更好的办法是,让类自身负责保存它的唯一实例。这个类可以保证没有其他实例可以被创建(通过截取创建新对象的请求),并且它可以提供一个访问该实例的方法。这就是Singleton模式。 3.适用性 在下面的情况下可以使用Singleton模式.当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时。当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。 4.结构 5.参与者 Singleton 定义一个GetInstance操作,允许客户访问它的唯一实例。GetInstance是一个类操作(即Smalltalk中的一个类方法和C++中的一个静态成员函数)。可能负责创建它自己的唯一实例。 6.协作 客户只能通过Singleton的GetInstance操作访问一个Singleton的实例。 7.效果 Singleton模式有许多优点: 1)对唯一实例的受控访问因为Singleton类封装它的唯一实例,所以它可以严格的控制客户怎样以及何时访问它。 2)缩小名空间Singleton模式是对全局变量的一种改进。它避免了那些存储唯一实例的全局变量污染名空间。 3)允许对操作和表示的精化Singleton类可以有子类,而且用这个扩展类的实例来配置一个应用是很容易的。你可以用你所需要的类的实例在运行时刻配置应用。 4)允许可变数目的实例这个模式使得你易于改变你的想法,并允许Singleton类的多个实例。此外,你可以用相同的方法来控制应用所使用的实例的数目。只有允许访问Singleton实例的操作需要改变。 5)比类操作更灵活另一种封装单件功能的方式是使用类操作(即C++中的静态成员函数或者是Smalltalk中的类方法)。但这两种语言技术都难以改变设计以允许一个类有多个实例。 此外,C++中的静态成员函数不是虚函数,因此子类不能多态的重定义它们。 8.实现 class Singleton { static std::auto_ptr protected: //prevent user making our any instance by manually //构造函数是保护类型的。 Singleton(){} public: ~Singleton(){} //Return this singleton class' instance pointer static Singleton* Instance() { if(!m_pInstance.get()) { m_pInstance = std::auto_ptr } return m_pInstance.get(); } }; 怎样来使用它呢?不要试图从这个类派生你的单件子类,那样的结果是不妥当的,如果你需要多个单件子类,还是使用下面的宏定义更为妥当: #define DEFINE_SINGLETON(cls) private: static std::auto_ptr protected: cls(){} public: ~cls(){} static cls* Instance(){ if(!m_pInstance.get()){ m_pInstance = std::auto_ptr } return m_pInstance.get(); } #define IMPLEMENT_SINGLETON(cls) std::auto_ptr 假定你需要实现一个单件类YY,这样书写: class YY { DEFINE_SINGLETON(YY); public: //your interfaces here...}; 在cpp文件中,书写: IMPLEMENT_SINGLETON(YY); 需要引入这个类的实例的时候,使用这样的语句: YY* pYY = YY::Instance(); 这,就是全部。 如果需要定义其他的单件类,重复上面的定义,就可以了。 当想集中管理一个应用程序所需的所有配置时,可以声明一个CToolsOptions的类,其中包含配置属性集合。对于这个类的实例,显然是一个实例就够了;当编写绘图程序时,考虑绘制矩形,圆形等分别使用CGraphTool派生的工具类,每个派生类负责处理具体的绘制动作和相关的UI相应逻辑。这些工具类典型的在被用户选择工具栏的图元按钮时被选中。依照这种模式,你应该对所有的图元工具从事注册工作,使得绘图程序了解运行时刻可以使用那些图元工具。同样的,负责管理注册信息的这个管理器也只需 P2467.6.2(1) 必须把它作为类成员函数的运算符有: (),[],->和任何赋值运算符,重载这些运算符时必须把操作符函数声明为类的成员函数 什么时候定义类成员操作符重载,什么时候定义非类成员操作符重载? 答:(1)如果一个重载操作符是类成员,那么只有当跟它一起使用的左操作数是该类对象时,它才会被调用,如果该操作符的左操作数必须是其他类型,那么重载操作符必须是非类成员操作符重载。 (2)C++要求,赋值(=),下标([ ]),调用(())和成员访问箭头(->)操作符必须被指定为类成员操作符,否则错误。第二篇:C++上机实验报告
第三篇:C++上机实验报告
第四篇:华中科技大学C++实验总结报告(图形编辑器)
第五篇:c++作业