资源描述
西安交大C++程序设计第十章作业
精品资料
西安交通大学实验报告
课程__计算机程序设计__实验名称__多态性__第 1 页 共 44 页
系 别____ ______ 实 验 日 期 2014 年 5 月 31 日
专业班级__ ____组别_____________ 实 验 报 告 日 期 2014 年 5 月 31 日
姓 名___ _____学号_ _ 报 告 退 发 ( 订正 、 重做 )
同 组 人_________________________________ 教 师 审 批 签 字
一、实验目的
理解掌握多态的使用方法,学会用虚函数。
二、实验内容
(一)第一题:定义一个类Base,该类含有虚函数display,然后定义它的两个派生类FirstB和SecondB,这两个派生类均含有公有成员函数display,在主程序中,定义指向基类Base的指针变量ptr,并分别定义Base、FirstB、Second的对象b1、f1、s1,让ptr分别指向b1、f1、s1的起始地址,然后指向执行这些对象的成员函数display。
1.源程序代码:
#include<iostream>
using namespace std;
class Base
{
public:
virtual void display()
{
cout<<"sound!sound!sound!";
}
};
class FirstB:public Base
{
public:
void virtual display()
{
cout<<"miao!miao!miao!";
}
};
class SecondB:public Base
{
public:
void virtual display()
{
cout<<"wang!wang!wang!";
}
};
int main()
{
Base *ptr;
Base b1;
FirstB f1;
SecondB s1;
cout<<"指向基类Base:\t";
ptr=&b1;
ptr->display();
cout<<"\n指向派生类FirstBase:\t";
ptr=&f1;
ptr->display();
cout<<"\n指向派生类SecondB:\t";
ptr=&s1;
ptr->display();
cout<<endl;
return 0;
}
2.实验结果:
(二)第二题: 扩充例10-5,从中派生一个正方形类和圆柱体类,写一个测试程序,输出正方形的面积和圆柱体的体积。
1.源程序代码:
//shape类shape.h文件
#ifndef SHAPE_H
#define SHAPE_H
#include<iostream>
using namespace std;
class Shape
{
public:
virtual double Area()const
{
return 0.0;
}//纯虚函数,在派生类中重载
virtual double Volume() const=0;
virtual void PrintShapeName() const=0;
virtual void Print() const=0;
};
#endif
//point.h点类
#ifndef POINT_H
#define POINT_H
#include<iostream>
#include"shape.h"
using namespace std;
class Point:public Shape
{
int x,y;
public:
Point(int a=0,int b=0)
{
SetPoint(a,b);
}
void SetPoint(int a,int b)
{
x=a;
y=b;
}
int GetX()
{
return x;
}
int GetY()
{
return y;
}
virtual double Volume() const
{
return 0.0;
}
virtual void PrintShapeName()const
{
cout<<"Point:";
}
virtual void Print()const
{
cout<<'['<<x<<","<<y<<']';
}
};
#endif
//circle.h圆类
#ifndef CIRCLE_H
#define CIRCLE_H
#include<iostream>
#include"point.h"
using namespace std;
class Circle:public Point
{
double radius;
public:
Circle(int x=0,int y=0,double r=0.0):Point(x,y)
{
SetRadius(r);
}
void SetRadius(double r)
{
radius=(r>=0?r:0);
}
double GetRadius() const
{
return radius;
}
virtual double Area() const
{
return 3.14159*radius*radius;
}
virtual double Volume() const
{
return 0.0;
}
virtual void PrintShapeName() const
{
cout<<"Circle:";
}
void Print() const
{
cout<<"Center=";
Point::Print();
cout<<";Radius="<<radius<<endl;
}
};
#endif
//rectangle.h矩形类
#ifndef RECTANGULAR_H
#define RECTANGULAR_H
#include<iostream>
#include"point.h"
using namespace std;
class Rectangle:public Point
{
double length,width;
public:
Rectangle(int x=0,int y=0,double l=0.0,double w=0.0):Point(x,y)
{
SetLength(l);
SetWidth(w);
}
void SetLength(double l)
{
length=(l>=0?l:0);
}
void SetWidth(double w)
{
width=(w>=0?w:0);
}
double GetLength() const
{
return length;
}
double GetWidth() const
{
return width;
}
virtual double Area() const
{
return length*width;
}
virtual double Volume() const
{
return 0.0;
}
virtual void Print() const
{
cout<<"Left Top Vertex=";
Point::Print();
cout<<";Length="<<length<<",Width="<<width<<endl;
}
virtual void PrintShapeName() const
{
cout<<"Rectangle:";
}
};
#endif
//cylinder.h圆柱体类
#ifndef CYLINDER_H
#define CYLINDER_H
#include"circle.h"
#include<iostream>
;using namespace std;
class Cylinder:public Circle
{
double height;
public:
Cylinder(int x=0,int y=0,double r=0,double h=0):Circle(x,y,r)
{
SetHeight(h);
}
void SetHeight(double h)
{
height=(h>=0?h:0);
}
double GetHeight() const
{
return height;
}
double Volume() const
{
return Area()*height;
}
virtual void PrintShapeName() const
{
cout<<"Cylinder:";
}
void Print() const
{
Circle::Print();
cout<<"Height="<<height<<endl;
}
};
#endif
//square.h正方形类,几乎跟矩形类一样而已
#ifndef SQUARE_H
#define Square_H
#include"rectangle.h"
#include<iostream>
using namespace std;
class Square:public Rectangle
{
double sidelength;
public:
Square(int x=0,int y=0,double s=0.0):Rectangle(x,y)
{
Seta(s);
}
void Seta(double s)
{
sidelength=s;
}
virtual double Area() const
{
return sidelength*sidelength;
}
virtual double Volume() const
{
return 0.0;
}
virtual void Print() const
{
cout<<"Left Top Vertex=";
Point::Print();
cout<<";Length="<<sidelength<<endl;
}
virtual void PrintShapeName() const
{
cout<<"Square:";
}
};
#endif
main.h//要求:派生出圆柱类和正方形类,计算面积、体积
#include<iostream>
#include"shape.h"
#include"point.h"
#include"circle.h"
#include"rectangle.h"
#include"square.h"
#include"cylinder.h"
using namespace std;//为何系统报错提示要输入一个“;”在此句首????
void virtualViaPointer(const Shape*);
void virtualViaReference(const Shape&);
int main()
{
//创建point circle rectangular对象信息
Point point(30,50);
Circle circle(120,80,10.0);
Rectangle rectangle(10,10,8.0,5.0);
Square square(10,20,5.0);
Cylinder cylinder(120,80,10.0,40.0);
//输出point circle rectangular 对象信息
point.PrintShapeName();
point.Print();
cout<<endl;
circle.PrintShapeName();
circle.Print();
rectangle.PrintShapeName();
rectangle.Print();
square.PrintShapeName();
square.Print();
cylinder.PrintShapeName();
cylinder.Print();
//定义基类对象指针
Shape *arrayOfShapes[5];//定义了个基类指针
arrayOfShapes[0]=&point;
arrayOfShapes[1]=&circle;
arrayOfShapes[2]=&rectangle;
arrayOfShapes[3]=□
arrayOfShapes[4]=&cylinder;
//通过基类对象指针访问派生类对象
cout<<"Virtual function calls made off"<<"base-class pointers\n";
for(int i=0;i<5;i++)
virtualViaPointer(arrayOfShapes[i]);
cout<<"Virtual function calls made off"<<"base-case references\n";
for(int j=0;j<5;j++)
virtualViaReference(*arrayOfShapes[j]);
return 0;
}
//通过基类对象访问虚函数实现动态绑定???
void virtualViaPointer(const Shape*baseClassPtr)
{
baseClassPtr->PrintShapeName();
baseClassPtr->Print();
cout<<"Area="<<baseClassPtr->Area();
cout<<"\tVolume="<<baseClassPtr->Volume()<<endl;
}
//通过基类对象引用访问虚函数实现动态绑定???
void virtualViaReference(const Shape &baseClassRef)
{
baseClassRef.PrintShapeName();
baseClassRef.Print();
cout<<"Area="<<baseClassRef.Area();
cout<<"\tVolume="<<baseClassRef.Volume()<<endl;
}
2.实验结果:
(三)第三题: 扩充实例编程中的日期类,为Date增加一个成员函数,可以判断日期是否为系统当前日期。从键盘输入你的生日,如果今天是你的生日则显示:“Harry Birthday!”否则显示“还有**天是你的生日”或者“你的生日已经过去了** 天,距离明年生日还有**天”。
1.源程序代码:
// 日期类定义date.h
#ifndef DATE_H
#define DATE_H
#include <iostream>
using namespace std;
class Date {
int day,month,year;
void IncDay(); //日期增加一天
int DayCalc() const; //距基准日期的天数
static const int days[]; //每月的天数
public:
Date( int y, int m, int d); //构造函数
Date( int m, int d); //构造函数,年默认为系统当前年份
Date(); //构造函数,默认为系统日期
void SystemDate();
void SetDate( int yy, int mm, int dd ); //日期设置
void SetDate( int mm, int dd ); //日期设置,年默认为系统年份
bool IsLeapYear(int yy) const; // 是否闰年?
bool IsEndofMonth() const; // 是否月末?
void print_ymd() const; //输出日期yy_mm_dd
void print_mdy() const; //输出日期mm_dd_yy
const Date &operator+(int days); // 日期增加任意天
const Date &operator+=(int days); // 日期增加任意天
int operator-(const Date& ymd)const; // 两个日期之间的天数
void Show(Date& da);
};
#endif
// Date类成员函数定义date.cpp
#include <iostream>
#include <time.h>
#include "date.h"
using namespace std;
const int Date::days[] = { 0, 31, 28, 31, 30, 31, 30,
31, 31, 30, 31, 30, 31 };
//构造函数
Date::Date(int y,int m,int d) { SetDate(y,m,d); }
Date::Date(int m,int d) { SetDate(m,d); }
Date::Date() {SystemDate();}
void Date::SystemDate()
{ //取得系统日期
tm *gm;
time_t t=time(NULL);
gm = gmtime(&t);
year = 1900 + gm->tm_year;
month = gm->tm_mon +1;
day = gm->tm_mday;
}
void Date::SetDate( int yy, int mm, int dd )
{
month = ( mm >= 1 && mm <= 12 ) ? mm : 1;
year = ( yy >= 1900 && yy <= 2100 ) ? yy : 1900;
if ( month == 2 && IsLeapYear( year ) )
day = ( dd >= 1 && dd <= 29 ) ? dd : 1;
else
day = ( dd >= 1 && dd <= days[ month ] ) ? dd : 1;
}
void Date::SetDate(int mm, int dd )
{
tm *gm;
time_t t=time(NULL);
gm = gmtime(&t);
month = ( mm >= 1 && mm <= 12 ) ? mm : 1;
year = 1900 + gm->tm_year;
if ( month == 2 && IsLeapYear( year ) )
day = ( dd >= 1 && dd <= 29 ) ? dd : 1;
else
day = ( dd >= 1 && dd <= days[ month ] ) ? dd : 1;
}
const Date &Date::operator+( int days )
{ //重载+
for ( int i = 0; i < days; i++ )
IncDay();
return *this;
}
const Date &Date::operator+=( int days )
{ //重载+=
for ( int i = 0; i < days; i++ )
IncDay();
return *this;
}
int Date::operator-(const Date& ymd )const
{ //重载-
int days;
days = DayCalc()-ymd.DayCalc();
return days;
}
bool Date::IsLeapYear( int y ) const
{
if ( y % 400 == 0 || ( y % 100 != 0 && y % 4 == 0 ) )
return true;
return false;
}
bool Date::IsEndofMonth() const
{
if ( month == 2 && IsLeapYear( year ) )
return day == 29; //二月需要判断是否闰年
else
return day == days[ month ];
}
void Date::IncDay()
{ //日期递增一天
if ( IsEndofMonth())
if (month == 12){ // 年末
day = 1;
month = 1;
year++;
}
else { // 月末
day = 1;
month++;
}
else day++;
}
int Date::DayCalc() const
{
int dd;
int yy = year - 1900;
dd = yy*365;
if(yy) dd += (yy-1)/4;
for(int i=1;i<month;i++)
dd += days[i];
if(IsLeapYear(year)&&(month>2))
dd++;
dd += day;
return dd;
}
void Date::print_ymd() const
{
cout << year << "-" << month << "-" << day << endl;
}
void Date::print_mdy() const
{
char *monthName[ 12 ] = {"January",
"February", "March", "April", "May", "June",
"July", "August", "September", "October",
"November", "December" };
cout << monthName[ month-1 ] << ' '
<< day << ", " << year << endl;
}
void Date::Show(Date& da)
{
if(day==da.day&&month==da.month)
cout<<"Happy Birthday!";
else
{
if(da-Date::Date()<0)
da.year++;
cout<<"It will be your birthday after "<<da-Date::Date()<<" days!";
}
}
//扩充实例编程中的日期类,为Date增加一个成员函数,可以判断日期是否为系统当前日期。
//从键盘输入你的生日,如果今天是你的生日则显示:“Harry Birthday!
//”否则显示“还有**天是你的生日”或者“你的生日已经过去了** 天,距离明年生日还有**天”。
#include <iostream>
#include "date.h"
using namespace std;
int main()
{
Date today,Olympicday(2004,8,13);
cout << "Today (the computer's day) is: ";
today.print_ymd();
cout << "After 365 days, the date is: ";
today += 365;
today.print_ymd();
Date testday(2,28);
cout << "the test date is: ";
testday.print_ymd();
Date nextday = testday + 1;
cout << "the next date is: ";
nextday.print_ymd();
today.SystemDate();
cout << "the Athens Olympic Games openday is: ";
Olympicday.print_mdy();
cout << "And after " << Olympicday-today
<< " days, the Athens Olympic Games will open." <<endl;
cout<<"Please input your birthday:";
int a,b;
cin>>a>>b;
Date birthday(a,b);
today.Show(birthday);
cout<<endl;
return 0;
}
2.实验结果:
四、第四题:完成上一章实验第5题红颜色的函数功能:
5、 采用继承方式 定义一个三层生日蛋糕类,不论基类还是派生类都至少包含 5 个函数:构造函数、设置数据成员函数、求蛋糕体积、运算符 > 重载函数、输出生日祝词与蛋糕形状函数。并编写主函数测试各成员函数。继承方式如下:首先定义圆柱体形状蛋糕类,只有 3 个数据成员,半径、高、生日祝词。然后派生出圆柱体 _ 方柱体蛋糕类,即在圆柱体形状上增加方柱体形状。假定方柱体的正方形面积小于圆柱体的圆形面积,注意方柱体的高与正方形的边长不一定相等。再用圆柱体 _ 方柱体蛋糕类派生出圆柱体 _ 方柱体 _ 菱形体蛋糕类,即在方柱体形状上增加菱形柱体形状。假定菱形柱体的菱形面积小于方柱体的正方形面积。提示: ① 运算符 > 重载指两个蛋糕对象的体积大小。 ②基类和派生类数据成员不能定义为 public 。③ 设置数据成员函数、求蛋糕体积、求蛋糕表面积函数、输出生日祝词与蛋糕形状函数均为同名重载函数,例如分别采用函数名为 init() 、 volume() 、 area() 、 output() 。程序运行参考图如下:(红颜色的功能下一章实验完成)
1.源程序代码:
//yuan.h圆类头文件
#ifndef YUAN_H
#define YUAN_H
class Yuan
{
int YuanH,YuanR;
char Word[50];
public:
Yuan()
{
YuanH=0;
YuanR=0;
strcpy(Word,"Happy Birthday!");
}
Yuan(int h,int r,char word[])
{
Set(h,r,word);
}
void Set(int h,int r,char word[])
{
YuanH=h;
YuanR=r;
strcpy(Word,word);
}
double Vol()
{
return YuanH*YuanR*YuanR*3.14159;
}
double Area()
{
return 2*(YuanH*YuanR*3.14159+3.14159*YuanR*YuanR);
}
void Print()
{
cout<<Word;
cout<<"\n圆形蛋糕:";
cout<<"半径:"<<YuanR<<"\t高:"<<YuanH<<"\t体积:"<<Vol()<<"\t表面积:"<<Area();
}
Yuan operator >(Yuan& y)
{
if(Vol()>y.Vol())
cout<<"第一个蛋糕大";
if(Vol()==y.Vol())
cout<<"两个蛋糕一样大";
if(Vol()<y.Vol())
cout<<"第二个蛋糕大";
}
};
#endif
//yuanfang.h圆方类头文件
#ifndef YUAN_FANG_H
#define YUAN_FANG_H
#include<iostream>
#include"yuan.h"
class Yuan_Fang:public Yuan
{
int FangH,FangS;
public:
Yuan_Fang()
{
FangH=0;
FangS=0;
Yuan::Set(0,0,"Happy birthday!");
}
Yuan_Fang(int yuanh,int yuanr,int fangh,int fangs,char word[])
{
Set(yuanh,yuanr,fangh,fangs,word);
}
void Set(int yuanh,int yuanr,int fangh,int fangs,char word[])
{
Yuan::Set(yuanh,yuanr,word);
FangH=fangh;
FangS=fangs;
}
double Vol()
{
return Yuan::Vol()+FangH*FangS*FangS;
}
double Area()
{
return 4*FangH*FangS+2*FangS*FangS;
}
double Areato()
{
return Area()+Yuan::Area()-2*FangS*FangS;
}
void Print()
{
Yuan::Print();
cout<<"\n方形蛋糕:";
cout<<"高:"<<FangH<<"\t底边长:"<<FangS<<"\t体积:"<<Vol()<<"\t表面积:"<<Area();
}
Yuan_Fang operator >(Yuan_Fang& yf)
{
if(Vol()>yf.Vol())
cout<<"第一个蛋糕大";
if(Vol()==yf.Vol())
cout<<"两个蛋糕一样大";
if(Vol()<yf.Vol())
cout<<"第二个蛋糕大";
}
};
#endif
//yuanfangling.h圆方菱类头文件
#ifndef YUAN_FANG_LING_H
#define YUAN_FANG_LING_H
#include<iostream>
#include"yuanfang.h"
using namespace std;
class Yuan_Fang_Ling:public Yuan_Fang
{
int LingH;
int LingA;
int LingB;
public:
Yuan_Fang_Ling()
{
Yuan_Fang::Set(0,0,0,0,"Happy birthday to you!");
LingH=0;
LingA=0;
LingB=0;
}
Yuan_Fang_Ling(int yuanh,int yuanr,int fangh,int fangs,int lingh,int linga,int lingb,char word[])
{
Set(yuanh,yuanr,fangh,fangs,lingh,linga,lingb,word);
}
void Set(int yuanh,int yuanr,int fangh,int fangs,int lingh,int linga,int lingb,char word[])
{
Yuan_Fang::Set(yuanh,yuanr,fangh,fangs,word);
LingH=lingh;
LingA=linga;
LingB=lingb;
}
double Vol()
{
return Yuan_Fang::Vol()+LingH*LingA*LingB/2;
}
double Area()
{
return LingA*LingB+2*LingH*(LingA+LingB);
}
double Areato()
{
return Yuan_Fang::Areato()+Area()-LingA*LingB;
}
void Print()
{
Yuan_Fang::Print();
cout<<"\n菱形蛋糕:";
cout<<" 高:"<<LingH<<"\t 长轴长:"<<LingA<<"\t 短轴长:"<<LingB<<"\t 体积:"<<Vol()<<"\t表面积:"<<Area();
cout<<"\n总体积:"<<Yuan::Vol()+Yuan_Fang::Vol()+Vol();
cout<<"\t总表面积:"<<Areato();
}
Yuan_Fang_Ling operator >(Yuan_Fang_Ling& yfl)
{
if(Vol()>yfl.Vol())
cout<<"第一个蛋糕大";
if(Vol()==yfl.Vol())
cout<<"两个蛋糕一样大";
if(Vol()<yfl.Vol())
cout<<"第二个蛋糕大";
return *this;
}
};
#endif
//main.cpp
#include<iostream>
using namespace std;
#include"yuan.h"
#include"yuanfang.h"
#include"yuanfangling.h"
int
展开阅读全文