基于上篇C++ 多态:Shape类层次结构https://mp.csdn.net/mp_blog/creation/editor/133175074
一、【问题描述】
- 使用C++ 多态:Shape类层次结构中实现的Shape类层次。仅限于二维形状,如正方形,长方形、三角形和圆。
- 和用户进行交互,让用户指定形状、位置和大小;以及绘制每个形状时所用的填充字符。
- 用户可以指定多于一个的同样形状。
- 当你创建每个形状时,都将指向新Shape 对象的一个Shape*指针添加到一个数组中。每个 Shape 类应用它自己的 draw 成员函数。
- 编写一个遍历上述数组的多态的屏幕管理器,向数组中的每个对象发送draw消息,以形成屏幕图像。
- 每次当用户指定新添的一个形状时,要重新绘制整个屏幕图像。
二、【目的】
验证OOP的多态性,包括函数重载、虚函数;掌握采用OOP的多态特性解决问题的方法。
三、【具体解决方法】
1.创建Shape类作为基类。
//Shape类
class Shape
{
public:
virtual double getArea(){}//计算面积
virtual double getVolume(){}//计算体积
virtual void print(){}//打印
virtual void draw(int x,int y,char c){}//绘制形状
Shape(){}//构造
~Shape(){}//析构
};
2.创建二维类TwoDimensionalShape,继承于Shape类。
class TwoDimensionalShape : public Shape//二维
{
public:
TwoDimensionalShape(){}
virtual double getArea(){}
virtual void print(){}
virtual void draw(int x,int y,char c){}
};
3.正方形类Square,继承于二维类TwoDimensionalShape。我设计的draw()是利用二维数组(即画布就是矩形的),将正方形内的点置为1,其他为0,然后遍历数组,是1就输出,然后就可以实现draw这个功能。
class Square : public TwoDimensionalShape//二维的正方形
{
public:
Square(){}
Square(double side)
{
side_m=side;
}
double getArea()
{
return side_m*side_m;
}
void print()
{
cout<<"二维的正方形的面积为:"<<getArea()<<endl;
}
void draw(int x,int y,char c)
{
int a[50][50];
for(int i=0;i<50;i++)
{
for(int j=0;j<50;j++)
{
a[i][j]=0;
}
}
for(int i=0;i<50;i++)
{
for(int j=0;j<50;j++)
{
if(j>=x-1 && j<x+side_m-1 && i>=y-1 && i<y+side_m-1)
{
a[i][j]=1;
}
if(j>=x-2 && j<x+side_m && i>=y-2 && i<y+side_m && a[i][j]!=1)
{
a[i][j]=2;
}
}
}
for(int i=0;i<50;i++)
{
cout<<endl;
for(int j=0;j<50;j++)
{
if(a[i][j]==1)
cout<<c<<" ";
else
cout<<" ";
}
}
}
private:
double side_m;//边长
};
4.长方形类Rectangle,继承于二维类TwoDimensionalShape。draw()所用的方法与正方形的思想一样。
class Rectangle_ : public TwoDimensionalShape//二维的长方形
{
public:
Rectangle_(){}
Rectangle_(double length,double width)
{
length_m=length;
width_m=width;
}
double getArea()
{
return length_m*width_m;
}
void draw(int x,int y,char c)
{
int a[50][50];
for(int i=0;i<50;i++)
{
for(int j=0;j<50;j++)
{
a[i][j]=0;
}
}
for(int i=0;i<50;i++)
{
for(int j=0;j<50;j++)
{
if(j>=x-1 && j<x+length_m-1 && i>=y-1 && i<y+width_m-1)
{
a[i][j]=1;
}
if(j>=x-2 && j<x+length_m && i>=y-2 && i<y+width_m && a[i][j]!=1)
{
a[i][j]=2;
}
}
}
for(int i=0;i<50;i++)
{
cout<<endl;
for(int j=0;j<50;j++)
{
if(a[i][j]==1)
cout<<c<<" ";
else
cout<<" ";
}
}
}
void print()
{
cout<<"二维的长方形的面积为:"<<getArea()<<endl;
}
private:
double length_m;//长
double width_m;//宽
};
5.三角形类Triangle,继承于二维类TwoDimensionalShape。规定的是等腰直角三角形(好吧就是因为这个好画),所用的方法与前面两个的思想一样。
class Triangle : public TwoDimensionalShape//二维的三角形 (这里定义为等腰直角三角形)
{
public:
Triangle(){}
Triangle(double side)
{
side_m=side;
}
double getArea()
{
return 0.5*side_m*side_m;
}
void draw(int x,int y,char c)
{
int a[50][50];
for(int i=0;i<50;i++)
{
for(int j=0;j<50;j++)
{
a[i][j]=0;
}
}
for(int i=0,k=-y+2;i<50;i++,k++)
{
for(int j=0;j<50;j++)
{
if(j>=x-1 && j<x+k-1 && i>=y-1 && i<y+side_m-1)
{
a[i][j]=1;
}
if(j>=x-2 && j<x+k && i>=y-3 && i<y+side_m && a[i][j]!=1)
{
a[i][j]=2;
}
}
}
for(int i=0;i<50;i++)
{
cout<<endl;
for(int j=0;j<50;j++)
{
if(a[i][j]==1)
cout<<c<<" ";
else
cout<<" ";
}
}
}
void print()
{
cout<<"二维的三角形的面积为:"<<getArea()<<endl;
}
private:
double side_m;//等腰直角三角形的边长
};
6.圆形类Circle,继承于二维类TwoDimensionalShape (在这里我想说一下,关于画圆以及如何填充圆,推荐参考文章 Bresenham 画圆算法原理)。因为我们事先固定了画布的范围,所以需要注意的是圆的半径是有规定输入范围的。还有,因为对Bresenham画圆算法学的不好,就学会了画圆的轮廓,还不会填充T-T。
class Circle : public TwoDimensionalShape//二维的圆形
{
public:
Circle(){}
Circle(double radius)
{
radius_m=radius;
}
double getArea()
{
return E*radius_m*radius_m;
}
void draw(int x,int y,char c)
{
//1=<r<=24
int a[50][50];
for(int i=0;i<50;i++)
{
for(int j=0;j<50;j++)
{
a[i][j]=0;
}
}
int r=x;
int p;
x=0;
y=r;
p=3-2*r;
for(;x<=y;x++)
{
a[ x+r][ y+r]=1;
a[ x+r][-y+r]=1;
a[-x+r][ y+r]=1;
a[-x+r][-y+r]=1;
a[ y+r][ x+r]=1;
a[ y+r][-x+r]=1;
a[-y+r][ x+r]=1;
a[-y+r][-x+r]=1;
if(p>=0)
{
p+=4*(x-y)+10;
y--;
}
else
{
p+=4*x+6;
}
}
for(int i=0;i<50;i++)
{
cout<<endl;
for(int j=0;j<50;j++)
{
if(a[i][j]==1)
cout<<c<<" ";
else
cout<<" ";
}
}
}
void print()
{
cout<<"二维的圆形的面积为:"<<getArea()<<endl;
}
private:
double radius_m;//圆的半径
};
7.绘制图形。设计交互,让用户选择填充字符。
char cinColor()
{
char c;
int color;
cout<<"填充字符有:1.'*' 2.'#' 3.'@' 4.'&'"<<endl;
cout<<"请输入你想绘制该形状的填充字符(编号),若超出范围则默认为'&':"<<endl;
cin>>color;
if(color==1)
c='*';
else if(color==2)
c='#';
else if(color==3)
c='@';
else
c='&';
return c;
}
8.测试程序功能。
int main()
{
char cinColor();
vector<Shape*> shapeclass;
vector<Shape*>::iterator iter;
int a;
int x,y;
a=-1;
while(a!=0)
{
cout<<"******二维形状图形********"<<endl
<<"********1.正方形**********"<<endl
<<"********2.长方形**********"<<endl
<<"********3.三角形**********"<<endl
<<"********4.圆形************"<<endl
<<"********0.退出************"<<endl;
cout<<"请输入你所选择的形状(编号):"<<endl;
cin>>a;
switch(a)
{
case 1:
{
double side;
cout<<"Please enter the side of square:"<<endl;
cin>>side;
Shape *ptr_Square=new Square(side);
shapeclass.push_back(ptr_Square);
iter = shapeclass.begin();
(*iter)->print();
char ch=cinColor();
cout<<"请输入图形的起始坐标:"<<endl;
cin>>x>>y;
(*iter)->draw(x,y,ch);
delete ptr_Square;
}
break;
case 2:
{
double length,width;
cout<<"Please enter the length and width of the rectangle:"<<endl;
cin>>length>>width;
Shape *ptr_Rectangle_=new Rectangle_(length,width);
shapeclass.push_back(ptr_Rectangle_);
iter = shapeclass.begin();
(*iter)->print();
char ch=cinColor();
cout<<"请输入图形的起始坐标:"<<endl;
cin>>x>>y;
(*iter)->draw(x,y,ch);
delete ptr_Rectangle_;
}
break;
case 3:
{
double side;
cout<<"Please enter the side of the triangle: "<<endl;
cin>>side;
Shape *ptr_Triangle=new Triangle(side);
shapeclass.push_back(ptr_Triangle);
iter = shapeclass.begin();
(*iter)->print();
char ch=cinColor();
cout<<"请输入图形的起始坐标:"<<endl;
cin>>x>>y;
(*iter)->draw(x,y,ch);
delete ptr_Triangle;
}
break;
case 4:
{
double radius;
cout<<"Please enter the radius of Circle(0<radius<=24): "<<endl;
cin>>radius;
Shape *ptr_Circle=new Circle(radius);
shapeclass.push_back(ptr_Circle);
iter = shapeclass.begin();
(*iter)->print();
char ch=cinColor();
x=y=radius;
(*iter)->draw(x,y,ch);
delete ptr_Circle;
}
break;
case 0:
{
a=0;
}
break;
}
system("pause");
system("cls");
cout<<endl;
}
return 0;
}
四、【完整代码】
//
//(使用Shape类层次结构的多态性的屏幕管理器)开发一个基本图形软件包
/
#include<iostream>
#include<vector>
#include<math.h>
#include<windows.h>
using namespace std;
#define E 3.14
//Shape类
class Shape
{
public:
virtual double getArea(){}//计算面积
virtual double getVolume(){}//计算体积
virtual void print(){}//打印
virtual void draw(int x,int y,char c){}//绘制形状
Shape(){}//构造
~Shape(){}//析构
};
class TwoDimensionalShape : public Shape//二维
{
public:
TwoDimensionalShape(){}
virtual double getArea(){}
virtual void print(){}
virtual void draw(int x,int y,char c){}
};
class Square : public TwoDimensionalShape//二维的正方形
{
public:
Square(){}
Square(double side)
{
side_m=side;
}
double getArea()
{
return side_m*side_m;
}
void print()
{
cout<<"二维的正方形的面积为:"<<getArea()<<endl;
}
void draw(int x,int y,char c)
{
int a[50][50];
for(int i=0;i<50;i++)
{
for(int j=0;j<50;j++)
{
a[i][j]=0;
}
}
for(int i=0;i<50;i++)
{
for(int j=0;j<50;j++)
{
if(j>=x-1 && j<x+side_m-1 && i>=y-1 && i<y+side_m-1)
{
a[i][j]=1;
}
if(j>=x-2 && j<x+side_m && i>=y-2 && i<y+side_m && a[i][j]!=1)
{
a[i][j]=2;
}
}
}
for(int i=0;i<50;i++)
{
cout<<endl;
for(int j=0;j<50;j++)
{
if(a[i][j]==1)
cout<<c<<" ";
else
cout<<" ";
}
}
}
private:
double side_m;//边长
};
class Rectangle_ : public TwoDimensionalShape//二维的长方形
{
public:
Rectangle_(){}
Rectangle_(double length,double width)
{
length_m=length;
width_m=width;
}
double getArea()
{
return length_m*width_m;
}
void draw(int x,int y,char c)
{
int a[50][50];
for(int i=0;i<50;i++)
{
for(int j=0;j<50;j++)
{
a[i][j]=0;
}
}
for(int i=0;i<50;i++)
{
for(int j=0;j<50;j++)
{
if(j>=x-1 && j<x+length_m-1 && i>=y-1 && i<y+width_m-1)
{
a[i][j]=1;
}
if(j>=x-2 && j<x+length_m && i>=y-2 && i<y+width_m && a[i][j]!=1)
{
a[i][j]=2;
}
}
}
for(int i=0;i<50;i++)
{
cout<<endl;
for(int j=0;j<50;j++)
{
if(a[i][j]==1)
cout<<c<<" ";
else
cout<<" ";
}
}
}
void print()
{
cout<<"二维的长方形的面积为:"<<getArea()<<endl;
}
private:
double length_m;//长
double width_m;//宽
};
class Triangle : public TwoDimensionalShape//二维的三角形 (这里定义为等腰直角三角形)
{
public:
Triangle(){}
Triangle(double side)
{
side_m=side;
}
double getArea()
{
return 0.5*side_m*side_m;
}
void draw(int x,int y,char c)
{
int a[50][50];
for(int i=0;i<50;i++)
{
for(int j=0;j<50;j++)
{
a[i][j]=0;
}
}
for(int i=0,k=-y+2;i<50;i++,k++)
{
for(int j=0;j<50;j++)
{
if(j>=x-1 && j<x+k-1 && i>=y-1 && i<y+side_m-1)
{
a[i][j]=1;
}
if(j>=x-2 && j<x+k && i>=y-3 && i<y+side_m && a[i][j]!=1)
{
a[i][j]=2;
}
}
}
for(int i=0;i<50;i++)
{
cout<<endl;
for(int j=0;j<50;j++)
{
if(a[i][j]==1)
cout<<c<<" ";
else
cout<<" ";
}
}
}
void print()
{
cout<<"二维的三角形的面积为:"<<getArea()<<endl;
}
private:
double side_m;//等腰直角三角形的边长
};
class Circle : public TwoDimensionalShape//二维的圆形
{
public:
Circle(){}
Circle(double radius)
{
radius_m=radius;
}
double getArea()
{
return E*radius_m*radius_m;
}
void draw(int x,int y,char c)
{
//1=<r<=24
int a[50][50];
for(int i=0;i<50;i++)
{
for(int j=0;j<50;j++)
{
a[i][j]=0;
}
}
int r=x;
int p;
x=0;
y=r;
p=3-2*r;
for(;x<=y;x++)
{
a[ x+r][ y+r]=1;
a[ x+r][-y+r]=1;
a[-x+r][ y+r]=1;
a[-x+r][-y+r]=1;
a[ y+r][ x+r]=1;
a[ y+r][-x+r]=1;
a[-y+r][ x+r]=1;
a[-y+r][-x+r]=1;
if(p>=0)
{
p+=4*(x-y)+10;
y--;
}
else
{
p+=4*x+6;
}
}
for(int i=0;i<50;i++)
{
cout<<endl;
for(int j=0;j<50;j++)
{
if(a[i][j]==1)
cout<<c<<" ";
else
cout<<" ";
}
}
}
void print()
{
cout<<"二维的圆形的面积为:"<<getArea()<<endl;
}
private:
double radius_m;//圆的半径
};
char cinColor()
{
char c;
int color;
cout<<"填充字符有:1.'*' 2.'#' 3.'@' 4.'&'"<<endl;
cout<<"请输入你想绘制该形状的填充字符(编号),若超出范围则默认为'&':"<<endl;
cin>>color;
if(color==1)
c='*';
else if(color==2)
c='#';
else if(color==3)
c='@';
else
c='&';
return c;
}
int main()
{
char cinColor();
vector<Shape*> shapeclass;
vector<Shape*>::iterator iter;
int a;
int x,y;
a=-1;
while(a!=0)
{
cout<<"******二维形状图形********"<<endl
<<"********1.正方形**********"<<endl
<<"********2.长方形**********"<<endl
<<"********3.三角形**********"<<endl
<<"********4.圆形************"<<endl
<<"********0.退出************"<<endl;
cout<<"请输入你所选择的形状(编号):"<<endl;
cin>>a;
switch(a)
{
case 1:
{
double side;
cout<<"Please enter the side of square:"<<endl;
cin>>side;
Shape *ptr_Square=new Square(side);
shapeclass.push_back(ptr_Square);
iter = shapeclass.begin();
(*iter)->print();
char ch=cinColor();
cout<<"请输入图形的起始坐标:"<<endl;
cin>>x>>y;
(*iter)->draw(x,y,ch);
delete ptr_Square;
}
break;
case 2:
{
double length,width;
cout<<"Please enter the length and width of the rectangle:"<<endl;
cin>>length>>width;
Shape *ptr_Rectangle_=new Rectangle_(length,width);
shapeclass.push_back(ptr_Rectangle_);
iter = shapeclass.begin();
(*iter)->print();
char ch=cinColor();
cout<<"请输入图形的起始坐标:"<<endl;
cin>>x>>y;
(*iter)->draw(x,y,ch);
delete ptr_Rectangle_;
}
break;
case 3:
{
double side;
cout<<"Please enter the side of the triangle: "<<endl;
cin>>side;
Shape *ptr_Triangle=new Triangle(side);
shapeclass.push_back(ptr_Triangle);
iter = shapeclass.begin();
(*iter)->print();
char ch=cinColor();
cout<<"请输入图形的起始坐标:"<<endl;
cin>>x>>y;
(*iter)->draw(x,y,ch);
delete ptr_Triangle;
}
break;
case 4:
{
double radius;
cout<<"Please enter the radius of Circle(0<radius<=24): "<<endl;
cin>>radius;
Shape *ptr_Circle=new Circle(radius);
shapeclass.push_back(ptr_Circle);
iter = shapeclass.begin();
(*iter)->print();
char ch=cinColor();
x=y=radius;
(*iter)->draw(x,y,ch);
delete ptr_Circle;
}
break;
case 0:
{
a=0;
}
break;
}
system("pause");
system("cls");
cout<<endl;
}
return 0;
}