C++实验六const对象和const成员、友元.doc_第1页
C++实验六const对象和const成员、友元.doc_第2页
C++实验六const对象和const成员、友元.doc_第3页
C++实验六const对象和const成员、友元.doc_第4页
C++实验六const对象和const成员、友元.doc_第5页
已阅读5页,还剩10页未读 继续免费阅读

下载本文档

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

文档简介

评语:评分项目评分内容分值评分结果预习情况是否完成预习工作。要求按实验指导书进行预习、并完成实验报告初稿、编写程序。20实验方案实验方案是否可行。要求目的、任务明确、原理清楚、步骤可操作、对实验过程数据有记录方案、对可能的错误有预备方案。30实验过程与结果实验结果是否正确。要求完成实验过程中的数据记录、记录要完整和准确、内容要详细,实验结果要与预期的正确结果一致。35实验结论实验结论是否正确。要求根据实验原理对实验过程中的数据、实验结果进行分析,得出实验结论。15总 分100 指导教师(签名) 年 月 日说明:指导教师评分后,实验报告交院(系)办公室保存。实验6 const对象和const成员、友元1实习目的及要求1)掌握coust对象、 coust成员函数和coust成员数据的使用;2)掌握友元函数的定义和使用。2预习1)预习coust对象及const成员的定义、使用等相关知识;2)预习友元的概念、友元成员函数、友元类等相关知识。预习知识总结:const声明格式注意常对象类名 const 对象名必须初始化,且不能改变(即:不能再次被赋值);常对象只能调用常成员函数类常成员函数类型说明符 函数名(参数表)const不能更新对象的数据成员,也不能调用该类中没有const修饰的成员函数。常数据成员Const 类型说明符 数据名任何函数不能对常数据成员赋值。构造函数对它初始化只能通过初始化列表类的友元友元通过友元关系一个普通函数或者类的成员函数可以访问封装于另外一个类中的数据友元函数在它的函数体中可通过对象名访问类的私有和保护成员(关键)友元类若A类为B类的友元类,友元类A的所有成员函数都自动成为B类的友元函数,都可以访问B类私有和保护成员UML语言例子友元函数+fDist(a:Piont &,b:Point &):float友元类类A类B常成员函数+print():void常数据成员-r:const int& -a:const int疑问:常引用和常对象的UML语言怎么表示3实验内容31分析下面的程序,观察编译程序时会出现什么样的错误。 #includeclass Sampleint n;public:Sample(int i)n=i;void setvalue(int i)n=i;void display()coutn=nendl;void main()const Sample s(5);s.setvalue(8); s.display(); 分析:明显在main部分,对象s被定义被初始化为一个对象常量,其成员数据是不可以被setvalue修改的。编译的时候出现了如下的错误:error C2662: setvalue : cannot convert this pointer from const class Sample to class Sample &Conversion loses qualifierserror C2662: display : cannot convert this pointer from const class Sample to class Sample &Conversion loses qualifiers所以应该修改为:void main()const Sample s(5);Sample s1(5);s.display();s1.setvalue(8);s1.display();这样的话,s1的成员函数才可以修改成员数据的值。32 编写并调试程序1).编写一个程序求直角坐标中一个点到直线的距离。要求设计一个点类point,含有两个公有成员数据x和y,代表点的坐标。另一个类为直线类line,它有三个私有成员数据a,d,c。分别代表直线方程ax+by+c=0的系数。在类line中设计一个友元函数distance计算一个点到直线的距离。点(x,y)到直线ax+by+c=0的距离distance的计算公式如下:请根据下面给出的部分程序编写直线类line及其成员函数,以组成完整的程序。#include#includeclass line;class pointpublic:float x, y;point(float i,float j)x=i;y=j;void main()point p1(2,4);line l1(1,2,3);coutdistance=distance(p1,l1)endl;a) 实验方案:分析用UML语言分析类line和类point的类图和对象图分析main部分的流程设计根据分析设计line类和友元函数distance的代码代码测试结合题目部分代码,在Visual C+平台编译,调试。如有语法错误,双击调试窗口错误的地方,纠正错误并作错误分析。如有逻辑错误,重新审核代码设计是否符合要求。结果预测点(2,4)到直线x+2y+3=0的距离为:(1*2+2*4+3)/(sqrt(1+2*2)=13/sqrt(5)=5.813776741实现记录最后的正确代码实现和结果b) 根据题意画出类point和类line的UML类图、对象图,如下图: c) main部分的流程分析:p1.x=2, p1=4;l1.a=1, l1.b=2, l1.c=3Distance=(fabs(p1.x*l1.a+p1.y*l1.b+l1.c)/(sqrt(l1.a* l1.a+ l1.b* l1.b)在屏幕上显示distance的值d) 代码设计:1.line类代码设计:class lineprivate:float a,b,c;public:line (float a1=0,float b1=0,float c1=0)a=a1;b=b1;c=c1;friend double distance(point &p,line &l);2.友元函数distance设计:double line:distance(point &p,line &l)return fabs(l.a*p.x+l.b*p.y+p.x)/(sqrt(l.a*l.a+l.b*l.b);e) 和题目部门代码组合并在Visual C+上编译调试,结果出现了以下问题错误分析:友元函数是在类中用关键字friend修饰的非成员函数,所以函数头double line:distance(point &p,line &l)明显把友元函数当成了类line里面的成员函数,导致编译的时候出现了语法错误。所以应该改为:再次运行没有错误显示,链接得出结果,结果截图如下:和预测的结果有出入,检查友元函数distance中的语句return fabs(l.a*p.x+l.b*p.y+p.x)/(sqrt(l.a*l.a+l.b*l.b);和公式对比发现设计错误return fabs(l.a*p.x+l.b*p.y+l.c)/(sqrt(l.a*l.a+l.b*l.b);得f) 总的代码实现如下:2)编写一类Cpoint表示一个点的信息。在此基础上编写一个表示三角形的类tria,顶点为其对象成员。编写完整的程序输出三角形的面积。要求用用友元函数来实现三角形面积的输出。a) 实验方案:分析用UML语言分析类tria和类Cpoint的类图三角形面积S=P(P-A)(P-B)(P-C), 其中P=(A+B+C)/2(A,B,C分别指三边长度设计根据分析设计类和友元函数的代码代码测试在Visual C+平台编译调试。如有语法错误,纠正错误并作错误分析。如有逻辑错误,逐条语句分析审核。结果预测以(0,0),(3,0),(0,4)为顶点的三角形面积为6以(0,3.0),(2.0,0)(-2.0,0)为顶点的三角形面积为6实现记录最后的正确代码实现和结果b) 根据题意用UML语言作出类Cpoint的类图,类tria的类图:类Cpoint是一个点(x,y)的信息,所以设计为拥有两个数据成员x,y和数据输入操作。而tria表示的一个三角形,三角形的静态属性为三个顶点,顶点之间的距离和三角形名字;其动态属性求三角形面积并输出,求两点间距离。类图如下: c) 代码设计:(1)Cpoint类代码设计:class Cpointprivate:float x,y;public:Cpoint(float a=0,float b=0)x=a;y=b;Cpoint(Cpoint &p)x=p.x;y=p.y;float getx() return x;float gety() return y;(2)tria类代码设计:class triaprivate:Cpoint a,b,c;float ab,bc,ca;double area;public:tria(Cpoint p1,Cpoint p2,Cpoint p3);double length(Cpoint p1,Cpoint p2);friend double getarea(tria &t1);tria:tria(Cpoint p1,Cpoint p2,Cpoint p3):a(p1),b(p2),c(p3)double tria:length(Cpoint p1,Cpoint p2)double x=double(p1.getx()-p2.getx();double y=double(p1.gety()-p2.gety();return sqrt(x*x+y*y);(3)友元函数getarea(tria t1)的代码设计:double getarea(tria &t1)t1.ab= t1.length(t1.a, t1.b);t1.bc= t1.length(t1.b, t1.c);t1.ca= t1.length(t1.c, t1.a);double p=(t1.ab+t1.bc+t1.ca)/2;t1.area=sqrt(p*(p- t1.ab)*(p- t1.bc)*(p- t1.ca);return t1.area;(4)main部分代码设计void main()Cpoint p1(0,0),p2(0,3),p3(4,0); tria A(p1,p2,p3);cout三角形的面积是getarea(A)endl;d) 在Visual c+中调试出现了一下错误错误分析:仔细检查,发现getarea的友元在类里面忘了写参数,它之前的语句少了分号。修改完之后编译,没有语法错误出现就链接,结果如下和结果预测中的以(0,0),(3,0),(0,4)为顶点的三角形面积为6一致。测试另外的数据(0,3.0),(2.0,0)(-2.0,0)的三角形,得结果再次与预测结果一致。就此认为,所编写程序是可执行的。e) 最终所求的代码为:*4 课后练习调试下列例程,指出程序实现的功能及程序输出结果,进一步理解coust对象及const成员的定义和使用。1)调试程序1 # include class CSample int a , b ; public : CSample (int x , int y ) a=x ; b=y; CSample ( ) void PrintAB( ) ;void PrintAB( ) const ; const void Test ( ) ; void CSample:PrintAB () / a=2 ; /Test ( ); cout调用函数CSample:PrintAB() n ; coutA=atB=bendl ; void CSample:PrintAB () const cout调用函数CSample:PrintAB() const !n ; coutA=atB=bendl ;/a=2 ; /Test ( ); void main ( ) CSample s1 (11 ,22 ) ; CSample const s2(33 ,44) ; s1.PrintAB() ; s2.PrintAB() ;a) 类图和对象图分析b) 功能分析:通过常对象和一般对象的调用类成员函数的区别说明常对象只能调用常成员函数,这也说明了const关键字可以用于对重载函数的区分,如类中:void PrintAB( ) ;void PrintAB( ) const ;打击哦对Print的有效重载。c) 疑问:常成员函数Test在类中充当什么角色?d) 结果预测:调用函数CSample:PrintAB()A=11 B=22调用函数CSample:PrintAB() const !A=33 B=44f)程序在Visual C+上的运行经过是:2)调试程序2# include class CIncrement int count ; const int increment ; public : CIncrement (int c=0 , int i =1 ) ; void addIncrement () count+=increment; void Print ( ) const ; ;CIncrement :CIncrement (int c , int i): increment ( i ) count=c ;void CIncrement :Print ( ) const /increment =2 ; coutcount=counttincrement=incrementn ;void main ( ) CIncrement value (10 ,5); coutBefore incrementing: ; value.Print() ; for (int j=1 ; j=3 ;j+ ) value.addIncrement ( ) ;coutAfter incrementj : ;value.Print ( ) ;a) 类图和对象图的分析如下:b) main部分流程分析:Before incrementing “count=10 ,increment=5在屏幕上显示count和increment的值j=1j=3 count+=increment; After increment value.Print ( ) ;结束c) 功能分析:increment被定义成常成员数据,构造函数通过初始化列表对它初始化后,任何函数不能对它赋值,所以它的值一直为5,而incrermenting则随for循环被addIncrement ()函数3次加5.d) 结果预测:Before incrementing count=10 ,increment=5 After increment count=15 ,increment=5After increment count=20 ,increment=5After increment count=25 ,increment=5f)调试结果如下,和预测一致:3)调试程序3# include class A2 ; class A1 int a , b ;public : A1(int i , int j)a=i ; b=j ; int Geta()return a ; int Getb()return b; void Change (A2 &) ; /A ;class A2 int c , d ;public : A2(int i ,int j) c=i , d=j ;int Getc()return c; int Getd()return d ;friend void A1:Change ( A2 &) ; ;void A1:Change(A2 &s1)a=s1.c ; b=s1.d ;void main ( ) A1 a1 (1 ,2) ; A2 a2 (3 ,4) ; couta1.a=a1.Geta()ta1.b=a1.Getb()endl ; couta2.c=a2.Getc()ta1.c=a2.Getd()endl ; a1.Change(a2) ; couta1.a=a1.Geta()ta1.b=a1.Getb()endl ;a) 类图和对象图分析如下:b) 功能分析:友元函数Change通过对象名直接访问类的私有c,d。c) 结果预测:a1.a=1 a1.b=2 a1.a=3 a1.2=4a1.a=3 a1.b=4d) 调试结果:4)调试程序4# includeclass CStack ; class CNode int data ; CNode *prev ;public : CNode (int d , CNode *n) data=d ; prev=n ; friend class CStack ; ;class CStack CNode *top ; public: CStack ( ) top=0 ; void push (int i ) ; int pop ( ) ; ;void CStack :push (int i ) CNode *n=new CNode (i , top) ; top = n ; int CS

温馨提示

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

评论

0/150

提交评论