c++实验抽象类Shape.docx
《c++实验抽象类Shape.docx》由会员分享,可在线阅读,更多相关《c++实验抽象类Shape.docx(15页珍藏版)》请在冰豆网上搜索。
c++实验抽象类Shape
华南农业大学信息(软件)学院
综合性、设计性实验成绩单
开设时间:
2013~2014年第二学期
专业
工业工程
班级
12工工2班
学号
姓名
实验题目
抽象类Shape类
自我评价
能够较好完成验证性实验,理解C++抽象类的概念及应用,学会利用重载函数针对不同需求进行重载,得到较简便较直观的运算方式;在设计实验中,能够仿照例程派生出正方形类和圆柱体类,并且输出所需参数;也能实现重载关系运算符函数后,直接对两个圆进行比较大小,并编写程序进行大小排序。
教师评语
评价指标:
●题目内容独立完成情况优□良□中□差□
●对算法原理的理解程度优□良□中□差□
●程序设计水平优□良□中□差□
●程序运行情况优□良□中□差□
●实验报告结构清晰优□良□中□差□
●实验总结和分析详尽优□良□中□差□
成绩
教师签名
1实验内容及目的
目的:
理解和掌握C++抽象类和具体类的实现,了解运算符重载。
实验内容:
1、从Point、Circle中抽象出基类Shape,研究抽象类和具体类的接口和实现。
2、从中派生出一个正方形类和圆柱体类,然后写一个测试程序,输出正方形的面积和圆柱体的体积。
3、在Circle类中实现关系运算符的重载,实现按半径对Circle对象排序。
2实验步骤
1.1首先建立基类Point、派生类:
Circle、Rectangle,然后抽象出基类Shape,实现虚函数的调用,输出面积、形状、坐标点等信息。
1.2编写测试函数,分别通过“基类对象指针访问虚函数”和“基类对象引用访问虚函数”两种方法实现抽象类和具体类的对接;
2.1再次派生出Cylinder、square两个类;
2.2同样依照第一小题,通过“基类对象指针访问虚函数”和“基类对象引用访问虚函数”两种方法实现抽象类Shape输出Cylinder、square两个派生类的面积或体积。
3.1在Circle类中编写关系运算符重载函数,用以判断两圆之间的半径大小:
例:
boolCircle:
:
operator<(Circlea)
{if(radiusreturntrue;
elsereturnfalse;
}
3.2编写测试程序对两圆按半径大小进行排序:
若两圆半径相等输出:
“两圆半径一样”,若两圆半径不等,按从小到大排序后输出圆信息。
3源代码
#ifndefSHAPE_H
#defineSHAPE_H
#include
usingnamespacestd;
classShape
{
public:
virtualdoubleArea()const{return0.0;}
virtualvoidPrintShapeName()const=0;
virtualvoidPrint()const=0;
};
#endif
#ifndefPOINT_H
#definePOINT_H
#include"shape.h"
usingnamespacestd;
classPoint:
publicShape
{intx,y;
public:
Point(int=0,int=0);//构造函数
voidSetPoint(int,int);//设置坐标
intGetX(){returnx;}//取x坐标
intGetY(){returny;}//取y坐标
virtualvoidPrintShapeName()const{cout<<"点坐标:
";}
virtualvoidPrint()const;//输出点的坐标
};
#endif
#include
#include"point.h"
usingnamespacestd;
Point:
:
Point(inta,intb){SetPoint(a,b);}
voidPoint:
:
SetPoint(inta,intb){x=a;y=b;}
voidPoint:
:
Print()const{cout<<'['<#ifndefCIRCLE_H
#defineCIRCLE_H
#include
#include"point.h"
usingnamespacestd;
classCircle:
publicPoint
{
doubleradius;
public:
Circle(intx=0,inty=0,doubler=0.0);
voidSetRadius(double);//设置半径
doubleGetRadius()const;//取半径
virtualdoubleArea()const;//计算面积
virtualvoidPrint()const;//输出圆心坐标和半径
virtualvoidPrintShapeName()const{cout<<"圆:
";}
doubleoperator=(Circle);
booloperator<(Circle);
booloperator>(Circle);
booloperator<=(Circle);
booloperator>=(Circle);
booloperator==(Circle);
booloperator!
=(Circle);
};
#endif
#include"circle.h"
usingnamespacestd;
Circle:
:
Circle(inta,intb,doubler):
Point(a,b)
{SetRadius(r);}
voidCircle:
:
SetRadius(doubler)
{radius=(r>=0?
r:
0);}
doubleCircle:
:
GetRadius()const{returnradius;}
doubleCircle:
:
Area()const{return3.14159*radius*radius;}
voidCircle:
:
Print()const
{
cout<<"圆心=";
Point:
:
Print();
cout<<";半径="<}
doubleCircle:
:
operator=(Circlea)
{
doubler;
r=a.radius;
return3.14159*r*r;
}
boolCircle:
:
operator<(Circlea)
{if(radiusreturntrue;
elsereturnfalse;
}
boolCircle:
:
operator>(Circleb)
{if(radius>b.radius)
returntrue;
elsereturnfalse;
}
boolCircle:
:
operator<=(Circleb)
{if(radius<=b.radius)
returntrue;
elsereturnfalse;
}
boolCircle:
:
operator>=(Circleb)
{if(radius>=b.radius)
returntrue;
elsereturnfalse;
}
boolCircle:
:
operator==(Circleb)
{if(radius==b.radius)
returntrue;
elsereturnfalse;
}
boolCircle:
:
operator!
=(Circleb)
{if(radius!
=b.radius)
returntrue;
elsereturnfalse;
}
#ifndefRECTANGLE_H
#defineRECTANGLE_H
#include
#include"point.h"
classRectangle:
publicPoint
{doublelength,width;
public:
Rectangle(intx=0,inty=0,doublel=0.0,doublew=0.0);
voidSetLength(double);//设置长度
voidSetWidth(double);//设置宽度
doubleGetLength()const;//取长度
doubleGetWidth()const;//取宽度
virtualdoubleArea()const;//计算面积
virtualvoidPrint()const;//输出坐标和尺寸
virtualvoidPrintShapeName()const{cout<<"矩形:
";}
};
#endif
#include"Rectangle.h"
usingnamespacestd;
Rectangle:
:
Rectangle(inta,intb,doublel,doublew):
Point(a,b)
{SetLength(l);SetWidth(w);}
voidRectangle:
:
SetLength(doublel){length=(l>=0?
l:
0);}
voidRectangle:
:
SetWidth(doublew)
{width=(w>=0?
w:
0);}
doubleRectangle:
:
GetLength()const{returnlength;}
doubleRectangle:
:
GetWidth()const{returnwidth;}
doubleRectangle:
:
Area()const
{returnlength*width;}
voidRectangle:
:
Print()const
{
cout<<"左上角坐标=";
Point:
:
Print();
cout<<";Length="<}
#ifndefSQUARE_H
#defineSQUARE_H
#include
usingnamespacestd;
#include"Point.h"
classsquare:
publicPoint
{
doublelength;
public:
square(intx=0,inty=0,doublea=0.0);
voidSetlength(double);
doubleGetlength()const;
virtualdoubleArea()const;
virtualvoidPrint()const;
virtualvoidPrintShapeName()const{cout<<"正方形:
";}
};
#endif
#include"square.h"
usingnamespacestd;
square:
:
square(inta,intb,doublec):
Point(a,b)
{Setlength(c);}
voidsquare:
:
Setlength(doublec){length=(c>=0?
c:
0);}
doublesquare:
:
Getlength()const{returnlength;}
doublesquare:
:
Area()const
{
returnlength*length;
}
voidsquare:
:
Print()const
{
cout<<"左上角坐标=";
Point:
:
Print();
cout<<";Length="<}
#ifndefCYLINDER_H
#defineCYLINDER_H
#include
#include"Circle.h"
usingnamespacestd;
classCylinder:
publicCircle
{
doublehigh;
doubleradius;
public:
Cylinder(intx=0,inty=0,doubler=0.0,doubleh=0.0);
voidSethigh(double);//设置高度
doubleGethigh()const;//取高度
virtualdoubleArea()const;//计算面积
virtualvoidPrint()const;//输出坐标和尺寸
virtualvoidPrintShapeName()const{cout<<"圆柱体:
";}
};
#endif
#include"Cylinder.h"
usingnamespacestd;
Cylinder:
:
Cylinder(intx,inty,doubler,doubleh):
Circle(x,y,r){Sethigh(h);}
voidCylinder:
:
Sethigh(doubleh){high=(h>=0?
h:
0);}
doubleCylinder:
:
Gethigh()const{returnhigh;}
doubleCylinder:
:
Area()const{return3.14*radius*high;}
voidCylinder:
:
Print()const
{
cout<<"底圆";
Circle:
:
Print();
cout<<"high="<}
#include
#include"shape.h"
#include"point.h"
#include"circle.h"
#include"Rectangle.h"
#include"square.h"
#include"Cylinder.h"
usingnamespacestd;
voidvirtualViaPointer(constShape*);
voidvirtualViaReference(constShape&);
intmain()
{
Pointpoint(6,5);
Circlecircle(10,80,10.0);
Circlecircle1(20,80,9.5);
Rectanglerectangle(50,5,8.0,5.0);
squaresquare(20,22,5);
Cylindercylinder(20,80,2.0,5.0);
//输出对象信息
point.PrintShapeName();
point.Print();
circle.PrintShapeName();
circle.Print();
circle1.PrintShapeName();
circle1.Print();
rectangle.PrintShapeName();
rectangle.Print();
square.PrintShapeName();
square.Print();
cylinder.PrintShapeName();
cylinder.Print();
cout<//定义基类对象指针
Shape*arrayOfShapes[6];
arrayOfShapes[0]=&point;
arrayOfShapes[1]=&circle;
arrayOfShapes[2]=&circle1;
arrayOfShapes[3]=&rectangle;
arrayOfShapes[4]=□
arrayOfShapes[5]=&cylinder;
cout<<"对两个圆类进行排序:
"<if(circle==circle1)
{
cout<<"两圆半径一样"<}
else
{
if(circle{
circle.PrintShapeName();
circle.Print();
circle1.PrintShapeName();
circle1.Print();
cout<<"排序完成"<}
elseif(circle>circle1)
{
circle1.PrintShapeName();
circle1.Print();
circle.PrintShapeName();
circle.Print();
cout<<"排序完成"<cout<}
}
//通过基类对象指针访问派生类对象
cout<<"通过基类对象指针访问虚函数:
\n";
for(inti=0;i<6;i++)
virtualViaPointer(arrayOfShapes[i]);
cout<cout<<"通过基类对象引用访问虚函数:
\n";
for(intj=0;j<6;j++)
virtualViaReference(*arrayOfShapes[j]);
return0;
}
//通过基类对象指针访问虚函数
voidvirtualViaPointer(constShape*baseClassPtr)
{baseClassPtr->PrintShapeName();
baseClassPtr->Print();
cout<<"Area="<Area()<}
//通过基类对象引用访问虚函数
voidvirtualViaReference(constShape&baseClassRef)
{
baseClassRef.PrintShapeName();
baseClassRef.Print();
cout<<"Area="<}
4遇到的问题与分析
1、对研究抽象类Shape与具体类的接口和实现。
如何实现抽象类和具体类的对接是一个难点,研究书本的例子,是有两种方法可以实现对接:
通过基类对象引用访问虚函数以及通过基类对象指针访问虚函数;这两种方法均可以实现调用某个具体类的虚函数,从而我开始尝试在新派生出来的圆柱体、正方形类中构建虚函数,并且在测试函数中增加对这两个具体类的调用函数,从而实现了利用抽象类调用具体类的虚函数。
2、构建对Circle的关系运算符重载函数
对Circle的关系运算符重载包括(<,<=,==,!
=,>,>=),首先我们需要定义每个运算符的重载函数(运算符函数)如:
boolCircle:
:
operator<(Circlea)
{if(radiusreturntrue;
elsereturnfalse;}
重载了“<”运算符,如此就可以直接对比两个圆的大小:
如if(circle5实验体会
第一个实验,遇到的问题特别多,前两题是验证性实验,照本宣科地打完代码后运行发现很多小错误,只能一个个排查,而且刚接触C++跟C语言相比感觉难很多,文件就多了一堆,出现一个错误,有可能并不在当前文件夹,而是在.h文件夹里,或是关联的文件里。
于是对于排错工作增加不少难度。
于是自己上网查找错误原因,请教同学比较厉害的同学等等方法用尽,方才实现了前两个实验,到了后面的函数重载,听课就不太懂,编写更有难度,于是网上找到一些资料,自己参考课本的例子,终于写出来了。