任务描述
本关任务:阅读代码,完善shape类家族,按继承派生关系,依次为Shape --> Point-->Circle -->Cyliner , 其中 A-->B表示B public 继承了A。注意,按下面要求做,不允许自己开放接口,即类的定义中不允许随意添加成员函数。
实训要求:
- 修改shape.h中类的定义,使得Shape类为抽象类,其中成员函数getArea和getVolume应定义为虚函数,成员函数getName和Print已定义为纯虚函数。注意,不允许自己添加成员函数。
- 根据注释,学习并理解shape.cpp中Shape类 Point类和Circle 类的实现,复习派生类的构造函数,继承体系中成员函数的访问控制,以及类型兼容规则
- 根据注释要求,在shape.cpp中补充实现Cylinder类的成员函数 getArea(), getVolume()
- 根据注释,学习理解main.cpp中以下两个通用函数的功能和意义
void DrawAll( Shape * );
void DrawViaRef( Shape &baseClassRef );`
- 根据注释要求,在main.cpp中指定位置补充代码
在此处可以选择文件
测试说明
平台会对你编写的代码进行测试:
测试输入:3 3 10 10
预期输出:
Virtual function calls made off base-class pointers:
I am Point: [7, 11]
my area is 0.00
my volume is 0.00
I am Circle: center is [22, 8]; radius is 3.50
my area is 38.48
my volume is 0.00
I am Cylinder: center is [10, 10]; radius is 3.30; height is 10.00
my area is 275.66
my volume is 342.12
call DrawViaRef(cir2) cir2 was constructed by copying cir1
Circle: center is [22, 8]; radius is 3.50
area is 38.48
volume is 0.00
call DrawViaRef(cy2)
Cylinder: center is [3, 3]; radius is 10.00; height is 10.00
area is 1256.32
volume is 3141.59
Cylinder cy2's base area, surface area and volume are: 314.16 1256.32 3141.59
开始你的任务吧,祝你成功!
答案
main.cpp
#include <iostream>
#include <iomanip>
using namespace std;
#include "shape.h"
// 体会通过基类指针调用虚函数实现多态
// 该函数将输出参数baseClassPtr指向的对象的形状名称,对象信息,面积和体积
void DrawAll(Shape * baseClassPtr);
// 学习体会通过基类的引用调用虚函数 实现多态,形参baseClassRef的类型是Shape&
// 输出参数baseClassRef引用的对象的形状名称,对象信息,面积和体积
void DrawViaRef(Shape & baseClassRef);
int main()
{
// set floating-point number format
cout << fixed << setprecision(2);
Point p(7, 11); // create a Point
Circle cir1(22, 8, 3.5); // create a Circle
Cylinder cy1(10, 10, 3.3, 10); // create a Cylinder
// create vector of three base-class pointers
Shape * shapePtr[3];
// aim shapePtr[0] at derived-class Point object
shapePtr[0] = &p;
// aim shapePtr[1] at derived-class Circle object
shapePtr[1] = &cir1;
// aim shapePtr[2] at derived-class Cylinder object
shapePtr[2] = &cy1;
cout << "\nVirtual function calls made off "
<< "base-class pointers:\n\n";
for (int i = 0; i < 3; i++)
DrawAll(shapePtr[i]);
double x, y, r, h;
cin >> x >> y >> r >> h;
Circle cir2(cir1); // cir2通过复制cir1构造,若没有自定义复制构造函数,系统会自动生成复制
Cylinder cy2;
//将x y r h的值分别赋给cy2的 x y radius height, 输出cy的底面积,表面积和体积
cy2.setPoint(x, y);
cy2.setRadius(r);
cy2.setHeight(h);
//函数DrawViaReference采用传引用的方式,传递的是基类的引用
//请观察当实参为circle对象和Cylinder对象时,函数的执行结果分别是什么,体会多态的含义
cout << "call DrawViaRef(cir2) cir2 was constructed by copying cir1\n";
DrawViaRef(cir2);
cout << "call DrawViaRef(cy2)\n";
DrawViaRef(cy2);
cout << "Cylinder cy2's base area, surface area and volume are: ";
/*****Begin*****/
cout << cy2.Circle::getArea() << ' ' << cy2.getArea() << ' ' << cy2.getVolume() << endl;
/*****End*****/
return 0;
} // end main
// 通过基类指针调用虚函数
// 该函数将输出参数baseClassPtr指向的对象的形状名称,对象信息,面积和体积
void DrawAll(Shape * baseClassPtr)
{
cout << "I am " << baseClassPtr->getName() << ": ";
baseClassPtr->print();
cout << "\n my area is " << baseClassPtr->getArea()
<< "\n my volume is " << baseClassPtr->getVolume()
<< "\n\n";
} // end function virtualViaPointer
// 通过基类的引用调用虚函数 实现动态联编,形参baseClassRef的类型是Shape&
// 输出参数baseClassRef引用的对象的形状名称,对象信息,面积和体积
void DrawViaRef(Shape& baseClassRef)
{
cout << baseClassRef.getName() << ": ";
baseClassRef.print();
cout << "\narea is " << baseClassRef.getArea()
<< "\nvolume is " << baseClassRef.getVolume() << "\n\n";
} // end function DrawViaRef
shape.cpp
// Fig. 10.13: shape.cpp
// Shape class member-function definitions.
#include <iostream>
#include "shape.h" // Shape class definition
using namespace std;
// return area of shape; 0.0 by default
double Shape::getArea()
{
return 0.0;
} // end function getArea
// return volume of shape; 0.0 by default
double Shape::getVolume()
{
return 0.0;
} // end function getVolume
// default constructor
Point::Point(int xValue, int yValue)
: x(xValue), y(yValue)
{
// empty body
} // end Point constructor
//重新定义纯虚函数getName,返回"Point"
string Point::getName()
{
return "Point";
} // end function getName
//重新定义纯虚函数print: 输出点的信息
void Point::print()
{
cout << '[' << x << ", " << y << ']';
} // end function print
// Circle的缺省构造函数
Circle::Circle(int xValue, int yValue, double radiusValue)
: Point(xValue, yValue) // call base-class constructor
{
radius = radiusValue;
} // end Circle constructor
// 计算并返回周长
double Circle::getCircumference()
{
return 6.28 * radius;
} // end function getCircumference
//重新定义虚函数getArea,返回圆的面积
double Circle::getArea()
{
return 3.14159 * radius * radius;
} // end function getArea
//重新定义纯虚函数getName,返回"Circle"
string Circle::getName()
{
return "Circle";
} // end function getName
//重新定义纯虚函数Print,输出圆的信息
void Circle::print()
{
cout << "center is ";
Point::print(); // invoke Point's print function
cout << "; radius is " << radius;
} // end function print
///Cylinder/
//*************Begin**************/
// 缺省构造函数
Cylinder::Cylinder(int xValue, int yValue, double radiusValue, double heightValue)
: Circle(xValue, yValue, radiusValue)
{
height = heightValue;
} // end Cylinder constructor
//重新定义虚函数getArea,返回圆柱体的表面积
double Cylinder::getArea()
{
return 2 * Circle::getArea() + getCircumference() * height;
} // end function getArea
//重新定义虚函数getVolume: 返回圆柱体的体积
double Cylinder::getVolume()
{
return Circle::getArea() * height;
} // end function getVolume
/*****************End*********/
//重新定义纯虚函数getName,返回"Cylinder"
string Cylinder::getName()
{
return "Cylinder";
} // end function getName
//重新定义纯虚函数getName,输出圆柱体的信息
void Cylinder::print()
{
Circle::print(); // code reuse
cout << "; height is " << height;
} // end function print
shape.h
#ifndef SHAPE_H_INCLUDED
#define SHAPE_H_INCLUDED
#include <string>
using namespace std;
/********** Begin **********/
class Shape {
public:
virtual double getArea();// 虚函数 返回面积
virtual double getVolume(); // 虚函数 返回体积
// 纯虚函数,必须在派生类中被重写
virtual string getName() = 0; // return shape name
virtual void print() = 0; // output shape
}; // end class Shape
class Point : public Shape {
public:
Point(int x = 0, int y = 0); // 缺省构造函数
void setPoint(int x, int y) { this->x = x; this->y = y; }// set x y坐标
virtual string getName();// 返回形状名称,即"Point"
virtual void print(); // 输出Point对象的信息
private:
int x; // x part of coordinate pair
int y; // y part of coordinate pair
}; // end class Point
class Circle : public Point {
public:
// default constructor
Circle(int = 0, int = 0, double = 0.0);
void setRadius(double r) { radius = r; } // 设置半径
double getCircumference(); // 返回周长
virtual double getArea(); //返回圆的面积
virtual string getName();// 返回形状名称,即"Circle")
virtual void print(); // 输出Circle对象的信息
private:
double radius; // Circle's radius
}; // end class Circle
class Cylinder : public Circle {
public:
// default constructor
Cylinder(int = 0, int = 0, double = 0.0, double = 0.0);
void setHeight(double h) { height = h; } // 设置圆柱体的高度
virtual double getArea(); //返回圆柱体的表面积
virtual double getVolume(); //返回圆柱体的体积
virtual string getName(); // 返回形状名称,即"Cylinder"
virtual void print(); // 输出Cylinder对象的信息
private:
double height; // Cylinder's height
}; // end class Cy
/********** End **********/
#endif // SHAPE_H_INCLUDED
用于本人在大学期间的学习记录