实现一系列图形的操作
描述:
使用C++语言编写一系列的类来实现形状相关的操作。要点如下:
- 设计一个抽象基类形状(Shape).这个抽象基类有周长、面积、形状类型等纯虚函数。
- 具体形状有三角形(triangle,用三条边长表示)、正方形(square)、长方形(rectangle)、梯形(trapezium,用上底、下底和左右边长表示)、圆形(round)、复合形状(compoundshape)。这些形状都是由Shape派生。
- 复合形状是指由多个形状组成的形状,组成复合形状的形状可以是普通形状,也可以是复合形状
- 一个复合形状的周长、面积都是它的各个子形状的和
要求:
运用类的派生、多态、组合等相关知识完成;
考虑使用设计模式来完善题目。
实现思路:
三角形
三角形用三条边长表示:假设三角形的三条边长为a、b、c
-
即三角形的三条边可能不合法
我们得判断:三角形任意两边之和都大于第三边
构 成 三 角 形 = { a + b > c a + c > b b + c > a 构成三角形 = \begin{cases}a+b>c\quad \text {} \\ a+c>b\quad \text{}\\ b+c>a \quad\text{} \end{cases} 构成三角形=⎩⎪⎨⎪⎧a+b>ca+c>bb+c>a -
即三角形的高我们不是可以直接知道的
通过海伦公式等推算得三角形的高
h = [ ( c + b + d - a ) ( b + d - a - c ) ( b + c - a - d ) ( a + c + d - b ) ] ½ / [ 2 ( b − a ) ] h={[(c+b+d-a)(b+d-a-c)(b+c-a-d)(a+c+d-b)]^½}/[2(b-a)] h=[(c+b+d-a)(b+d-a-c)(b+c-a-d)(a+c+d-b)]½/[2(b−a)]
梯形
梯形用四条边表示:设梯形的四条边为a、b、c、d
如图:
梯形可以拆成:矩形+三角形
即问题可以拆分为同上三角形的问题
虚析构函数
虚析构函数使得在删除指向子类对象的基类指针时可以调用子类的析构函数达到释放子类中堆内存的目的,而防止内存泄露的
设计模式
我对此作业的设计使用了:C++设计模式-Composite组合模式,组合模式依据树形结构来组合对象,用来表示部分以及整体层次。原理如图:
设计的Shape抽象图形基类,相当于图的Component类,声明了接口
virtual void getShape() = 0; //输出图形
virtual double getPerimeter() = 0; //返回周长
virtual double getArea() = 0; //返回面积
具体形状有基础图形三角形(Triangle)、正方形(Square)、长方形(Rectangle)、梯形(Trapezium)、圆形(Round),相当于图片的Leaf类,是Shape的具体实现。
复合形状(Compoundshape),相当于图像的Composite类,此类中特有的函数:add、remove,用于类的组合,可以组合普通图形也可以组合复合图形。
代码:
//抽象图形基类
class Shape
{
public:
virtual ~Shape()
{
cout << "~Shape" << endl;
};
virtual void getShape() = 0; //输出图形
virtual double getPerimeter() = 0; //返回周长
virtual double getArea() = 0; //返回面积
};
//长方形类
class Rectangle : public Shape
{
private:
double m_width,m_height; //长、宽
public:
Rectangle(double width, double height);
~Rectangle();
void getShape();
double getPerimeter();
double getArea();
};
Rectangle::Rectangle(double width, double height)
{
this->m_width = width;
this->m_height = height;
}
Rectangle::~Rectangle()
{
cout << "~Rectangle" << endl;
}
void Rectangle::getShape()
{
cout << "长方形 ";
}
double Rectangle::getPerimeter()
{
return m_height * 2 + m_width * 2;
}
double Rectangle::getArea()
{
return m_height * m_width;
}
//圆形类
class Round : public Shape
{
private:
double m_radius; //半径
public:
Round(double radius);
~Round();
void getShape();
double getPerimeter();
double getArea();
};
#define PI 3.1415
Round::Round(double radius)
{
this->m_radius = radius;
}
Round::~Round()
{
cout << "~Round" << endl;
}
void Round::getShape()
{
cout << "圆形 ";
}
double Round::getPerimeter()
{
return 2 * PI * m_radius;
}
double Round::getArea()
{
return PI * m_radius * m_radius;
}
//正方形类
class Square : public Shape
{
private:
double m_sideLength; //边长
public:
Square(double sideLength);
~Square();
void getShape();
double getPerimeter();
double getArea();
};
Square::Square(double sideLength)
{
this->m_sideLength = sideLength;
}
Square::~Square()
{
cout << "~Square" << endl;
}
void Square::getShape()
{
cout << "正方形 ";
}
double Square::getPerimeter()
{
return m_sideLength * 4;
}
double Square::getArea()
{
return m_sideLength * m_sideLength;
}
//梯形类
class Trapezium : public Shape
{
private:
double m_top, m_bottom, m_leftSide, m_rightSide; //上底、下底、左边长、右边长
public:
Trapezium(double top, double bottom, double leftSide, double rightSide);
~Trapezium();
double getHigh(); //获取梯形的高
void getShape();
double getPerimeter();
double getArea();
};
Triangle::Triangle(double leftSide, double rightSide, double bottom)
{
//能构成三角形的三边条件
if ((leftSide + rightSide > bottom) && (rightSide + bottom > leftSide) && (leftSide + bottom > rightSide))
{
this->m_bottom = bottom;
this->m_leftSide = leftSide;
this->m_rightSide = rightSide;
}
else //若不合法,赋值为0
{
this->m_bottom = 0;
this->m_leftSide = 0;
this->m_rightSide = 0;
}
}
Triangle::~Triangle()
{
cout << "~Triangle" << endl;
}
double Triangle::getHigh()
{
//除0不合法
if (m_bottom == 0 || m_leftSide == 0 || m_rightSide == 0)
return 0;
//知道三边长,计算出三角形的高
return ((sqrt((m_leftSide + m_rightSide + m_bottom) * (m_leftSide + m_bottom - m_rightSide) * (m_rightSide + m_bottom - m_leftSide) * (m_leftSide + m_rightSide - m_bottom))) / (2 * m_bottom));
}
void Triangle::getShape()
{
cout << "三角形 ";
}
double Triangle::getPerimeter()
{
return m_bottom + m_leftSide + m_rightSide;
}
double Triangle::getArea()
{
return m_bottom * getHigh() / 2;
}
//三角形类
class Triangle : public Shape
{
private:
double m_leftSide, m_rightSide, m_bottom; //左边长、右边长、下底
public:
Triangle(double leftSide, double rightSide, double bottom);
~Triangle();
double getHigh();
void getShape();
double getPerimeter();
double getArea();
};
Triangle::Triangle(double leftSide, double rightSide, double bottom)
{
//能构成三角形的三边条件
if ((leftSide + rightSide > bottom) && (rightSide + bottom > leftSide) && (leftSide + bottom > rightSide))
{
this->m_bottom = bottom;
this->m_leftSide = leftSide;
this->m_rightSide = rightSide;
}
else //若不合法,赋值为0
{
this->m_bottom = 0;
this->m_leftSide = 0;
this->m_rightSide = 0;
}
}
Triangle::~Triangle()
{
cout << "~Triangle" << endl;
}
double Triangle::getHigh()
{
//除0不合法
if (m_bottom == 0 || m_leftSide == 0 || m_rightSide == 0)
return 0;
//知道三边长,计算出三角形的高
return ((sqrt((m_leftSide + m_rightSide + m_bottom) * (m_leftSide + m_bottom - m_rightSide) * (m_rightSide + m_bottom - m_leftSide) * (m_leftSide + m_rightSide - m_bottom))) / (2 * m_bottom));
}
void Triangle::getShape()
{
cout << "三角形 ";
}
double Triangle::getPerimeter()
{
return m_bottom + m_leftSide + m_rightSide;
}
double Triangle::getArea()
{
return m_bottom * getHigh() / 2;
}
//组合图形类
class Compoundshape : public Shape
{
private:
list<Shape*> m_listShape; //存放图形指针的链表
int m_num; //由多少个图形组合而成
public:
Compoundshape();
~Compoundshape();
void add(Shape* pShape); //在复合图形里添加图形,仅复合图形里有这个函数
void remove(Shape* pShape);
void getShape();
double getPerimeter();
double getArea();
};
Compoundshape::Compoundshape()
{
m_num = 0; //复合图形,默认组合图形的个数初始化为0
};
Compoundshape::~Compoundshape()
{
cout << "~Compoundshape" << endl;
};
//在复合图形里添加图形,仅复合图形里有这个函数
//参数:图形指针
void Compoundshape::add(Shape* pShape)
{
if (pShape != NULL) {
m_listShape.push_back(pShape);
m_num++;
}
}
//在复合图形里删除图形,仅复合图形里有这个函数
//参数:图形指针
void Compoundshape::remove(Shape* pShape)
{
if (m_num != 0) {
list<Shape*>::iterator iter = m_listShape.begin();
for (; iter != m_listShape.end(); iter++)
{
if (*iter == pShape)
{
m_listShape.remove(pShape);
m_num--;
break;
}
}
}
}
void Compoundshape::getShape()
{
//自身图形输出
cout << "组合图形:";
//子图形输入
if (m_num != 0) {
//迭代遍历子图形,子图形可以是基础图形,也可以是复合图形(形成函数递归输出)
list<Shape*>::iterator iter = m_listShape.begin();
for (; iter != m_listShape.end(); iter++)
{
(*iter)->getShape();
cout << " ";
}
}
else
{
cout << "图形暂时为空 ";
}
}
double Compoundshape::getPerimeter()
{
double perimeterSum = 0;
list<Shape*>::iterator iter = m_listShape.begin();
for (; iter != m_listShape.end(); iter++)
{
perimeterSum += (*iter)->getPerimeter();
}
return perimeterSum;
}
double Compoundshape::getArea()
{
double areaSum = 0;
list<Shape*>::iterator iter = m_listShape.begin();
for (; iter != m_listShape.end(); iter++)
{
areaSum += (*iter)->getArea();
}
return areaSum;
}
/**************************************************************************
Author: YaoDemi
Date:2022-04-12
Description: Shape operation
**************************************************************************/
#include <iostream>
#include "Compoundshape.h"
#include "Rectangle.h"
#include "Round.h"
#include "Shape.h"
#include "Square.h"
#include "Trapezium.h"
#include "Triangle.h"
using namespace std;
int main()
{
//新建具体的基础图形
Shape* round = new Round(1);
Shape* rectangle = new Rectangle(4, 6);
Shape* square = new Square(2);
Shape* triangle = new Triangle(3, 4, 5);
Shape* trapezium = new Trapezium(2, 6, 3, 3);
cout << endl << "基本图形信息的输出" << endl;
round->getShape();
cout << " 周长:" << round->getPerimeter()
<< " 面积:" << round->getArea() << endl;
rectangle->getShape();
cout << " 周长:" << rectangle->getPerimeter()
<< " 面积:" << rectangle->getArea() << endl;
square->getShape();
cout << " 周长:" << square->getPerimeter()
<< " 面积:" << square->getArea() << endl;
triangle->getShape();
cout << " 周长:" << triangle->getPerimeter()
<< " 面积:" << triangle->getArea() << endl;
trapezium->getShape();
cout << " 周长:" << trapezium->getPerimeter()
<< " 面积:" << trapezium->getArea() << endl;
//新建一个复合图形a
Compoundshape* a = new Compoundshape();
a->add(round);
a->add(square);
a->add(rectangle);
cout << endl << "复合图形信息的输出" << endl;
a->getShape();
cout << " 周长:" << a->getPerimeter()
<< " 面积:" << a->getArea() << endl;
//新建一个复合图形b
Compoundshape* b = new Compoundshape();
b->add(triangle);
b->add(trapezium);
b->getShape();
cout << " 周长:" << b->getPerimeter()
<< " 面积:" << b->getArea() << endl;
//复合图形a中加入复合图形b
a->add(b);
a->getShape();
cout << " 周长:" << a->getPerimeter()
<< " 面积:" << a->getArea() << endl;
a->remove(b);
a->getShape();
cout << " 周长:" << a->getPerimeter()
<< " 面积:" << a->getArea() << endl;
//三角形三边不合法的情况下
cout << endl << "健壮性测试" << endl;
Shape* temp = new Triangle(1,1,2);
temp->getShape();
cout << " 周长:" << temp->getPerimeter()
<< " 面积:" << temp->getArea() << endl;
//释放空间
cout << endl << "空间释放测试" << endl;
delete round;
delete rectangle;
delete square;
delete triangle;
delete trapezium;
delete a;
delete b;
delete temp;
return 0;
}