• 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类作为基类。
    1. //Shape类
    2. class Shape
    3. {
    4. public:
    5. virtual double getArea(){}//计算面积
    6. virtual double getVolume(){}//计算体积
    7. virtual void print(){}//打印
    8. virtual void draw(int x,int y,char c){}//绘制形状
    9. Shape(){}//构造
    10. ~Shape(){}//析构
    11. };
    2.创建二维类TwoDimensionalShape,继承于Shape类。
    1. class TwoDimensionalShape : public Shape//二维
    2. {
    3. public:
    4. TwoDimensionalShape(){}
    5. virtual double getArea(){}
    6. virtual void print(){}
    7. virtual void draw(int x,int y,char c){}
    8. };
    3.正方形类Square,继承于二维类TwoDimensionalShape。我设计的draw()是利用二维数组(即画布就是矩形的),将正方形内的点置为1,其他为0,然后遍历数组,是1就输出,然后就可以实现draw这个功能。
    1. class Square : public TwoDimensionalShape//二维的正方形
    2. {
    3. public:
    4. Square(){}
    5. Square(double side)
    6. {
    7. side_m=side;
    8. }
    9. double getArea()
    10. {
    11. return side_m*side_m;
    12. }
    13. void print()
    14. {
    15. cout<<"二维的正方形的面积为:"<<getArea()<
    16. }
    17. void draw(int x,int y,char c)
    18. {
    19. int a[50][50];
    20. for(int i=0;i<50;i++)
    21. {
    22. for(int j=0;j<50;j++)
    23. {
    24. a[i][j]=0;
    25. }
    26. }
    27. for(int i=0;i<50;i++)
    28. {
    29. for(int j=0;j<50;j++)
    30. {
    31. if(j>=x-1 && j-1 && i>=y-1 && i-1)
    32. {
    33. a[i][j]=1;
    34. }
    35. if(j>=x-2 && j=y-2 && i1)
    36. {
    37. a[i][j]=2;
    38. }
    39. }
    40. }
    41. for(int i=0;i<50;i++)
    42. {
    43. cout<
    44. for(int j=0;j<50;j++)
    45. {
    46. if(a[i][j]==1)
    47. cout<" ";
    48. else
    49. cout<<" ";
    50. }
    51. }
    52. }
    53. private:
    54. double side_m;//边长
    55. };
    4.长方形类Rectangle,继承于二维类TwoDimensionalShape。draw()所用的方法与正方形的思想一样。
    1. class Rectangle_ : public TwoDimensionalShape//二维的长方形
    2. {
    3. public:
    4. Rectangle_(){}
    5. Rectangle_(double length,double width)
    6. {
    7. length_m=length;
    8. width_m=width;
    9. }
    10. double getArea()
    11. {
    12. return length_m*width_m;
    13. }
    14. void draw(int x,int y,char c)
    15. {
    16. int a[50][50];
    17. for(int i=0;i<50;i++)
    18. {
    19. for(int j=0;j<50;j++)
    20. {
    21. a[i][j]=0;
    22. }
    23. }
    24. for(int i=0;i<50;i++)
    25. {
    26. for(int j=0;j<50;j++)
    27. {
    28. if(j>=x-1 && j-1 && i>=y-1 && i-1)
    29. {
    30. a[i][j]=1;
    31. }
    32. if(j>=x-2 && j=y-2 && i1)
    33. {
    34. a[i][j]=2;
    35. }
    36. }
    37. }
    38. for(int i=0;i<50;i++)
    39. {
    40. cout<
    41. for(int j=0;j<50;j++)
    42. {
    43. if(a[i][j]==1)
    44. cout<" ";
    45. else
    46. cout<<" ";
    47. }
    48. }
    49. }
    50. void print()
    51. {
    52. cout<<"二维的长方形的面积为:"<<getArea()<
    53. }
    54. private:
    55. double length_m;//长
    56. double width_m;//宽
    57. };
    5.三角形类Triangle,继承于二维类TwoDimensionalShape。规定的是等腰直角三角形(好吧就是因为这个好画),所用的方法与前面两个的思想一样。
    1. class Triangle : public TwoDimensionalShape//二维的三角形 (这里定义为等腰直角三角形)
    2. {
    3. public:
    4. Triangle(){}
    5. Triangle(double side)
    6. {
    7. side_m=side;
    8. }
    9. double getArea()
    10. {
    11. return 0.5*side_m*side_m;
    12. }
    13. void draw(int x,int y,char c)
    14. {
    15. int a[50][50];
    16. for(int i=0;i<50;i++)
    17. {
    18. for(int j=0;j<50;j++)
    19. {
    20. a[i][j]=0;
    21. }
    22. }
    23. for(int i=0,k=-y+2;i<50;i++,k++)
    24. {
    25. for(int j=0;j<50;j++)
    26. {
    27. if(j>=x-1 && j-1 && i>=y-1 && i-1)
    28. {
    29. a[i][j]=1;
    30. }
    31. if(j>=x-2 && j=y-3 && i1)
    32. {
    33. a[i][j]=2;
    34. }
    35. }
    36. }
    37. for(int i=0;i<50;i++)
    38. {
    39. cout<
    40. for(int j=0;j<50;j++)
    41. {
    42. if(a[i][j]==1)
    43. cout<" ";
    44. else
    45. cout<<" ";
    46. }
    47. }
    48. }
    49. void print()
    50. {
    51. cout<<"二维的三角形的面积为:"<<getArea()<
    52. }
    53. private:
    54. double side_m;//等腰直角三角形的边长
    55. };
    6.圆形类Circle,继承于二维类TwoDimensionalShape (在这里我想说一下,关于画圆以及如何填充圆,推荐参考文章 Bresenham 画圆算法原理)。因为我们事先固定了画布的范围,所以需要注意的是圆的半径是有规定输入范围的。还有,因为对Bresenham画圆算法学的不好,就学会了画圆的轮廓,还不会填充T-T。
    1. class Circle : public TwoDimensionalShape//二维的圆形
    2. {
    3. public:
    4. Circle(){}
    5. Circle(double radius)
    6. {
    7. radius_m=radius;
    8. }
    9. double getArea()
    10. {
    11. return E*radius_m*radius_m;
    12. }
    13. void draw(int x,int y,char c)
    14. {
    15. //1=
    16. int a[50][50];
    17. for(int i=0;i<50;i++)
    18. {
    19. for(int j=0;j<50;j++)
    20. {
    21. a[i][j]=0;
    22. }
    23. }
    24. int r=x;
    25. int p;
    26. x=0;
    27. y=r;
    28. p=3-2*r;
    29. for(;x<=y;x++)
    30. {
    31. a[ x+r][ y+r]=1;
    32. a[ x+r][-y+r]=1;
    33. a[-x+r][ y+r]=1;
    34. a[-x+r][-y+r]=1;
    35. a[ y+r][ x+r]=1;
    36. a[ y+r][-x+r]=1;
    37. a[-y+r][ x+r]=1;
    38. a[-y+r][-x+r]=1;
    39. if(p>=0)
    40. {
    41. p+=4*(x-y)+10;
    42. y--;
    43. }
    44. else
    45. {
    46. p+=4*x+6;
    47. }
    48. }
    49. for(int i=0;i<50;i++)
    50. {
    51. cout<
    52. for(int j=0;j<50;j++)
    53. {
    54. if(a[i][j]==1)
    55. cout<" ";
    56. else
    57. cout<<" ";
    58. }
    59. }
    60. }
    61. void print()
    62. {
    63. cout<<"二维的圆形的面积为:"<<getArea()<
    64. }
    65. private:
    66. double radius_m;//圆的半径
    67. };
    7.绘制图形。设计交互,让用户选择填充字符。
    1. char cinColor()
    2. {
    3. char c;
    4. int color;
    5. cout<<"填充字符有:1.'*' 2.'#' 3.'@' 4.'&'"<
    6. cout<<"请输入你想绘制该形状的填充字符(编号),若超出范围则默认为'&':"<
    7. cin>>color;
    8. if(color==1)
    9. c='*';
    10. else if(color==2)
    11. c='#';
    12. else if(color==3)
    13. c='@';
    14. else
    15. c='&';
    16. return c;
    17. }
    8.测试程序功能。
    1. int main()
    2. {
    3. char cinColor();
    4. vector shapeclass;
    5. vector::iterator iter;
    6. int a;
    7. int x,y;
    8. a=-1;
    9. while(a!=0)
    10. {
    11. cout<<"******二维形状图形********"<
    12. <<"********1.正方形**********"<
    13. <<"********2.长方形**********"<
    14. <<"********3.三角形**********"<
    15. <<"********4.圆形************"<
    16. <<"********0.退出************"<
    17. cout<<"请输入你所选择的形状(编号):"<
    18. cin>>a;
    19. switch(a)
    20. {
    21. case 1:
    22. {
    23. double side;
    24. cout<<"Please enter the side of square:"<
    25. cin>>side;
    26. Shape *ptr_Square=new Square(side);
    27. shapeclass.push_back(ptr_Square);
    28. iter = shapeclass.begin();
    29. (*iter)->print();
    30. char ch=cinColor();
    31. cout<<"请输入图形的起始坐标:"<
    32. cin>>x>>y;
    33. (*iter)->draw(x,y,ch);
    34. delete ptr_Square;
    35. }
    36. break;
    37. case 2:
    38. {
    39. double length,width;
    40. cout<<"Please enter the length and width of the rectangle:"<
    41. cin>>length>>width;
    42. Shape *ptr_Rectangle_=new Rectangle_(length,width);
    43. shapeclass.push_back(ptr_Rectangle_);
    44. iter = shapeclass.begin();
    45. (*iter)->print();
    46. char ch=cinColor();
    47. cout<<"请输入图形的起始坐标:"<
    48. cin>>x>>y;
    49. (*iter)->draw(x,y,ch);
    50. delete ptr_Rectangle_;
    51. }
    52. break;
    53. case 3:
    54. {
    55. double side;
    56. cout<<"Please enter the side of the triangle: "<
    57. cin>>side;
    58. Shape *ptr_Triangle=new Triangle(side);
    59. shapeclass.push_back(ptr_Triangle);
    60. iter = shapeclass.begin();
    61. (*iter)->print();
    62. char ch=cinColor();
    63. cout<<"请输入图形的起始坐标:"<
    64. cin>>x>>y;
    65. (*iter)->draw(x,y,ch);
    66. delete ptr_Triangle;
    67. }
    68. break;
    69. case 4:
    70. {
    71. double radius;
    72. cout<<"Please enter the radius of Circle(0<
    73. cin>>radius;
    74. Shape *ptr_Circle=new Circle(radius);
    75. shapeclass.push_back(ptr_Circle);
    76. iter = shapeclass.begin();
    77. (*iter)->print();
    78. char ch=cinColor();
    79. x=y=radius;
    80. (*iter)->draw(x,y,ch);
    81. delete ptr_Circle;
    82. }
    83. break;
    84. case 0:
    85. {
    86. a=0;
    87. }
    88. break;
    89. }
    90. system("pause");
    91. system("cls");
    92. cout<
    93. }
    94. return 0;
    95. }
    四、【完整代码】
    1. //
    2. //(使用Shape类层次结构的多态性的屏幕管理器)开发一个基本图形软件包
    3. /
    4. #include
    5. #include
    6. #include
    7. #include
    8. using namespace std;
    9. #define E 3.14
    10. //Shape类
    11. class Shape
    12. {
    13. public:
    14. virtual double getArea(){}//计算面积
    15. virtual double getVolume(){}//计算体积
    16. virtual void print(){}//打印
    17. virtual void draw(int x,int y,char c){}//绘制形状
    18. Shape(){}//构造
    19. ~Shape(){}//析构
    20. };
    21. class TwoDimensionalShape : public Shape//二维
    22. {
    23. public:
    24. TwoDimensionalShape(){}
    25. virtual double getArea(){}
    26. virtual void print(){}
    27. virtual void draw(int x,int y,char c){}
    28. };
    29. class Square : public TwoDimensionalShape//二维的正方形
    30. {
    31. public:
    32. Square(){}
    33. Square(double side)
    34. {
    35. side_m=side;
    36. }
    37. double getArea()
    38. {
    39. return side_m*side_m;
    40. }
    41. void print()
    42. {
    43. cout<<"二维的正方形的面积为:"<<getArea()<
    44. }
    45. void draw(int x,int y,char c)
    46. {
    47. int a[50][50];
    48. for(int i=0;i<50;i++)
    49. {
    50. for(int j=0;j<50;j++)
    51. {
    52. a[i][j]=0;
    53. }
    54. }
    55. for(int i=0;i<50;i++)
    56. {
    57. for(int j=0;j<50;j++)
    58. {
    59. if(j>=x-1 && j-1 && i>=y-1 && i-1)
    60. {
    61. a[i][j]=1;
    62. }
    63. if(j>=x-2 && j=y-2 && i1)
    64. {
    65. a[i][j]=2;
    66. }
    67. }
    68. }
    69. for(int i=0;i<50;i++)
    70. {
    71. cout<
    72. for(int j=0;j<50;j++)
    73. {
    74. if(a[i][j]==1)
    75. cout<" ";
    76. else
    77. cout<<" ";
    78. }
    79. }
    80. }
    81. private:
    82. double side_m;//边长
    83. };
    84. class Rectangle_ : public TwoDimensionalShape//二维的长方形
    85. {
    86. public:
    87. Rectangle_(){}
    88. Rectangle_(double length,double width)
    89. {
    90. length_m=length;
    91. width_m=width;
    92. }
    93. double getArea()
    94. {
    95. return length_m*width_m;
    96. }
    97. void draw(int x,int y,char c)
    98. {
    99. int a[50][50];
    100. for(int i=0;i<50;i++)
    101. {
    102. for(int j=0;j<50;j++)
    103. {
    104. a[i][j]=0;
    105. }
    106. }
    107. for(int i=0;i<50;i++)
    108. {
    109. for(int j=0;j<50;j++)
    110. {
    111. if(j>=x-1 && j-1 && i>=y-1 && i-1)
    112. {
    113. a[i][j]=1;
    114. }
    115. if(j>=x-2 && j=y-2 && i1)
    116. {
    117. a[i][j]=2;
    118. }
    119. }
    120. }
    121. for(int i=0;i<50;i++)
    122. {
    123. cout<
    124. for(int j=0;j<50;j++)
    125. {
    126. if(a[i][j]==1)
    127. cout<" ";
    128. else
    129. cout<<" ";
    130. }
    131. }
    132. }
    133. void print()
    134. {
    135. cout<<"二维的长方形的面积为:"<<getArea()<
    136. }
    137. private:
    138. double length_m;//长
    139. double width_m;//宽
    140. };
    141. class Triangle : public TwoDimensionalShape//二维的三角形 (这里定义为等腰直角三角形)
    142. {
    143. public:
    144. Triangle(){}
    145. Triangle(double side)
    146. {
    147. side_m=side;
    148. }
    149. double getArea()
    150. {
    151. return 0.5*side_m*side_m;
    152. }
    153. void draw(int x,int y,char c)
    154. {
    155. int a[50][50];
    156. for(int i=0;i<50;i++)
    157. {
    158. for(int j=0;j<50;j++)
    159. {
    160. a[i][j]=0;
    161. }
    162. }
    163. for(int i=0,k=-y+2;i<50;i++,k++)
    164. {
    165. for(int j=0;j<50;j++)
    166. {
    167. if(j>=x-1 && j-1 && i>=y-1 && i-1)
    168. {
    169. a[i][j]=1;
    170. }
    171. if(j>=x-2 && j=y-3 && i1)
    172. {
    173. a[i][j]=2;
    174. }
    175. }
    176. }
    177. for(int i=0;i<50;i++)
    178. {
    179. cout<
    180. for(int j=0;j<50;j++)
    181. {
    182. if(a[i][j]==1)
    183. cout<" ";
    184. else
    185. cout<<" ";
    186. }
    187. }
    188. }
    189. void print()
    190. {
    191. cout<<"二维的三角形的面积为:"<<getArea()<
    192. }
    193. private:
    194. double side_m;//等腰直角三角形的边长
    195. };
    196. class Circle : public TwoDimensionalShape//二维的圆形
    197. {
    198. public:
    199. Circle(){}
    200. Circle(double radius)
    201. {
    202. radius_m=radius;
    203. }
    204. double getArea()
    205. {
    206. return E*radius_m*radius_m;
    207. }
    208. void draw(int x,int y,char c)
    209. {
    210. //1=
    211. int a[50][50];
    212. for(int i=0;i<50;i++)
    213. {
    214. for(int j=0;j<50;j++)
    215. {
    216. a[i][j]=0;
    217. }
    218. }
    219. int r=x;
    220. int p;
    221. x=0;
    222. y=r;
    223. p=3-2*r;
    224. for(;x<=y;x++)
    225. {
    226. a[ x+r][ y+r]=1;
    227. a[ x+r][-y+r]=1;
    228. a[-x+r][ y+r]=1;
    229. a[-x+r][-y+r]=1;
    230. a[ y+r][ x+r]=1;
    231. a[ y+r][-x+r]=1;
    232. a[-y+r][ x+r]=1;
    233. a[-y+r][-x+r]=1;
    234. if(p>=0)
    235. {
    236. p+=4*(x-y)+10;
    237. y--;
    238. }
    239. else
    240. {
    241. p+=4*x+6;
    242. }
    243. }
    244. for(int i=0;i<50;i++)
    245. {
    246. cout<
    247. for(int j=0;j<50;j++)
    248. {
    249. if(a[i][j]==1)
    250. cout<" ";
    251. else
    252. cout<<" ";
    253. }
    254. }
    255. }
    256. void print()
    257. {
    258. cout<<"二维的圆形的面积为:"<<getArea()<
    259. }
    260. private:
    261. double radius_m;//圆的半径
    262. };
    263. char cinColor()
    264. {
    265. char c;
    266. int color;
    267. cout<<"填充字符有:1.'*' 2.'#' 3.'@' 4.'&'"<
    268. cout<<"请输入你想绘制该形状的填充字符(编号),若超出范围则默认为'&':"<
    269. cin>>color;
    270. if(color==1)
    271. c='*';
    272. else if(color==2)
    273. c='#';
    274. else if(color==3)
    275. c='@';
    276. else
    277. c='&';
    278. return c;
    279. }
    280. int main()
    281. {
    282. char cinColor();
    283. vector shapeclass;
    284. vector::iterator iter;
    285. int a;
    286. int x,y;
    287. a=-1;
    288. while(a!=0)
    289. {
    290. cout<<"******二维形状图形********"<
    291. <<"********1.正方形**********"<
    292. <<"********2.长方形**********"<
    293. <<"********3.三角形**********"<
    294. <<"********4.圆形************"<
    295. <<"********0.退出************"<
    296. cout<<"请输入你所选择的形状(编号):"<
    297. cin>>a;
    298. switch(a)
    299. {
    300. case 1:
    301. {
    302. double side;
    303. cout<<"Please enter the side of square:"<
    304. cin>>side;
    305. Shape *ptr_Square=new Square(side);
    306. shapeclass.push_back(ptr_Square);
    307. iter = shapeclass.begin();
    308. (*iter)->print();
    309. char ch=cinColor();
    310. cout<<"请输入图形的起始坐标:"<
    311. cin>>x>>y;
    312. (*iter)->draw(x,y,ch);
    313. delete ptr_Square;
    314. }
    315. break;
    316. case 2:
    317. {
    318. double length,width;
    319. cout<<"Please enter the length and width of the rectangle:"<
    320. cin>>length>>width;
    321. Shape *ptr_Rectangle_=new Rectangle_(length,width);
    322. shapeclass.push_back(ptr_Rectangle_);
    323. iter = shapeclass.begin();
    324. (*iter)->print();
    325. char ch=cinColor();
    326. cout<<"请输入图形的起始坐标:"<
    327. cin>>x>>y;
    328. (*iter)->draw(x,y,ch);
    329. delete ptr_Rectangle_;
    330. }
    331. break;
    332. case 3:
    333. {
    334. double side;
    335. cout<<"Please enter the side of the triangle: "<
    336. cin>>side;
    337. Shape *ptr_Triangle=new Triangle(side);
    338. shapeclass.push_back(ptr_Triangle);
    339. iter = shapeclass.begin();
    340. (*iter)->print();
    341. char ch=cinColor();
    342. cout<<"请输入图形的起始坐标:"<
    343. cin>>x>>y;
    344. (*iter)->draw(x,y,ch);
    345. delete ptr_Triangle;
    346. }
    347. break;
    348. case 4:
    349. {
    350. double radius;
    351. cout<<"Please enter the radius of Circle(0<
    352. cin>>radius;
    353. Shape *ptr_Circle=new Circle(radius);
    354. shapeclass.push_back(ptr_Circle);
    355. iter = shapeclass.begin();
    356. (*iter)->print();
    357. char ch=cinColor();
    358. x=y=radius;
    359. (*iter)->draw(x,y,ch);
    360. delete ptr_Circle;
    361. }
    362. break;
    363. case 0:
    364. {
    365. a=0;
    366. }
    367. break;
    368. }
    369. system("pause");
    370. system("cls");
    371. cout<
    372. }
    373. return 0;
    374. }
    五、【运行结果展示】

    六、【绘制UML图】

  • 相关阅读:
    Python:if判断--综合案例练习:石头剪刀布
    RocketMQ之MappedFileQueue详解
    vtk for java 打包部署和运行
    软件测试之如何提升产品的用户体验度
    luffy-(8)
    linux部署nacos记录
    阿里云云原生一体化数仓 — 湖仓一体新能力解读
    redis主从复制玩法全过程笔记(redis7+版本)
    金仓数据库KingbaseES运维工具参考手册(6. 预防删除工具指南)
    平安大视野解读宏观经济:看好中国经济长期潜力,资产配置价值凸显
  • 原文地址:https://blog.csdn.net/weixin_74287172/article/details/133175333