基于C++的计算不同图形面积

要求

  1. 定义抽象基类Shape,由它派生出5个派生类:Circle、Square、Rectangle、Trapezoid、Triangle。用虚函数分别计算多个不同类图形的面积,并求它们的面积和。
  2. 要求用基类指针数组,使它的每一个元素指向一个派生类的对象,使用一个循环完成对多个图像的面积计算与求和。
  3. 图型的数据在定义对象时给定
  4. 定义顶点Point类,并在5个派生类中使用
  5. 圆以圆心坐标,半径的方式给定,其余以顶点坐标的方式给定
  6. 各个派生类的构造函数中应判断给定顶点组合是否满足图形属性

知识点

  1. 类的继承与派生
  2. 虚函数的使用

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
#include <iostream>
#include <math.h>
#include <stdlib.h>
#define pi 3.1415926
#define eps 1e-6
using namespace std;
//点类
class Point
{
public:
double x,y;
Point(){};
Point(double x,double y):x(x),y(y){};
Point &operator=(const Point &p){
x=p.x;
y=p.y;
return *this;
}
};
//基类
class Shape
{
public:
Point *p;
virtual double Area()=0;//求面积
bool check_angle90(Point a,Point b,Point c){//判断是否垂直
return fabs((a.x-c.x)*(b.x-c.x)+(b.y-c.y)*(a.y-c.y))<=eps;
}
bool check_Parallel(Point a,Point b,Point c,Point d){//判断是否平行
return fabs((a.x-b.x)*(c.y-d.y)-(a.y-b.y)*(c.x-d.x))<=eps;
}
double dis2(Point a,Point b){//求两点间距离
return pow(a.x-b.x,2)+pow(a.y-b.y,2);
}
void Swap(Point &x,Point &y){//交换两点
Point temp;
temp=x;
x=y;
y=temp;
}
};
//派生类:圆形
class Circle: public Shape
{
public:
double r;
Circle(Point point,double radius){
if(r<=0){
cout<<"Wrong parameter"<<endl;
}
p=new Point(point);
r=radius;
}
~Circle(){
delete p;
}
double Area(){
return r*r*pi;
}
};
//派生类:矩阵
class Rectangle: public Shape
{
public:
double width,height;
bool check(Point point[],bool isSquare){//判断是否是矩形或者正方形
int k=0;
while(k<3){//找到一个直角
if(check_angle90(point[0],point[1],point[2]))break;
Swap(point[k],point[3]);
k++;
}
if(k==3)return false;
Swap(point[1],point[2]);
double edge2[4];
for(int i=0;i<4;i++){
edge2[i]=dis2(point[i],point[(i+1)%4]);
}

//矩形两对边相等,正方形四边相等
if(isSquare)return fabs(edge2[0]-edge2[2])<=eps&&fabs(edge2[1]-edge2[3])<=eps&&fabs(edge2[0]-edge2[1])<=eps;
else return fabs(edge2[0]-edge2[2])<=eps&&fabs(edge2[1]-edge2[3])<=eps;
}
double Area(){
return width*height;
}
Rectangle(){};
Rectangle(Point point[]){
if(!check(point,0)){
cout<<"Wrong parameter"<<endl;
return;
}
p=new Point[4];
for(int i=0;i<4;i++){
p[i]=point[i];
}
width=sqrt(dis2(point[0],point[1]));
height=sqrt(dis2(point[0],point[3]));
}
~Rectangle(){
delete[] p;
}
};
//派生类:正方形
class Square: public Rectangle
{
public:
double edge;
Square(Point point[]){
if(!check(point,1)){
cout<<"Wrong parameter"<<endl;
return;
}
p=new Point[4];
for(int i=0;i<4;i++){
p[i]=point[i];
}
edge=sqrt(dis2(point[0],point[1]));
}
~Square(){
delete[] p;
}
double Area(){
return edge*edge;
}
};
//派生类:三角形
class Triangle: public Shape
{
public:
double edge[3];
bool check(Point point[]){//三角形只要判断是否有零边
for(int i=0;i<3;i++){
edge[i]=sqrt(dis2(point[i],point[(i+1)%3]));
}
return edge[0]>eps&&edge[1]>eps&&edge[2]>eps;
}
double Area(){//海伦公式
double aver=(edge[0]+edge[1]+edge[2])/2;
return sqrt(aver*(aver-edge[0])*(aver-edge[1])*(aver-edge[2]));
}
Triangle(Point point[]){
if(!check(point)){
cout<<"Wrong parameter"<<endl;
}
p=new Point[3];
for(int i=0;i<3;i++){
p[i]=point[i];
}
}
~Triangle(){
delete[] p;
}
};

class Trapezoid: public Shape
{
public:
bool check(Point point[]){
int i=0;
while(i<3){//找平行的一对边,为上下底
if(check_Parallel(point[0],point[1],point[2],point[3]))break;
Swap(point[i],point[3]);
i++;
}
if(i==3)return false;
//找高,且高不为零
double y0=point[0].y-point[1].y,x0=point[0].x-point[1].x;
if(fabs(x0)<=eps)height=fabs(point[0].x-point[2].x);
else {
double k=y0/x0;
double b1=point[0].y-k*point[0].x;
double b2=point[2].y-k*point[2].x;
height=fabs(b1-b2)/sqrt(1+k*k);
}
return height>eps;
}
double Area(){
return (topline+baseline)*height/2;
}
double height,topline,baseline;
Trapezoid(Point point[]){
if(!check(point)){
cout<<"Wrong parameter"<<endl;
}
p=new Point[4];
for(int i=0;i<4;i++){
p[i]=point[i];
}
topline=sqrt(dis2(point[0],point[1]));
baseline=sqrt(dis2(point[2],point[3]));
}
~Trapezoid(){
delete[] p;
}
};
int main()
{
Shape *p[5];
//圆心和半径
Point circlePoint(0.0,0.0);
double radius=5.5;
//长方形
Point rectVertex[4]={{0.0,0.0},{1.0,0.0},{1.0,2.0},{0.0,2.0}};
//正方形
Point squVertex[4]={{0.0,0.0},{4.8,3.6},{1.2,8.4},{-3.6,4.8}};
//三角形
Point triVertex[3]={{0.0,0.0},{4.6,8.9},{-4.3,4.2}};
//梯形
Point traVertex[4]={{0.0,0.0},{5.0,0.0},{1.0,7.0},{9.0,7.0}};
//Circle cir()
Circle cir(circlePoint,radius);
Rectangle rect(rectVertex);
Square squ(squVertex);
Triangle tri(triVertex);
Trapezoid tra(traVertex);

//调用各种派生类
p[0]=&cir;
p[1]=&rect;
p[2]=&squ;
p[3]=&tri;
p[4]=&tra;

double sumArea=0;
for(int i=0;i<4;i++){
sumArea+=p[i]->Area();
}
cout << sumArea << endl;
return 0;
}

运行结果

运行结果

结语

本次实验的重点在于类之间的继承和组合,以及对于纯虚函数的应用和类的成员函数的重复利用。
花在这份代码的时间其实大部分在构思如何判断形状。