C++ 多态:(使用Shape类层次结构的多态性的屏幕管理器)开发一个基本图形软件包。

基于上篇C++ 多态:Shape类层次结构icon-default.png?t=N7T8https://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;
}

五、【运行结果展示】

六、【绘制UML图】

猜你喜欢

转载自blog.csdn.net/weixin_74287172/article/details/133175333