【C++综合设计题】多层继承和抽象基类的综合应用

简介: 【C++综合设计题】多层继承和抽象基类的综合应用

题目要求


首先,声明一组多层继承关系的形状类族。从最抽象、最顶层的基类SHAPE(形状)开始,逐级向下派生出的各级子类依次为:POINT、LINE//CURVE、……、CUBE//CUBOID//DAM。详细的派生关系如下图所示。



具体的设计要求如下:

 通过键盘输入三角形的顶点:(0,0)、(5,0)、(3,6),输出其周长和面积;

 通过键盘输入正方形边长(9)和长方形边长(9、5),输出其周长和面积;

 通过键盘输入一个梯形坝体截面的顶点坐标:(0,0)、(2,4)、(6,4)、(8,

0)和坝体长度:28,输出其表面积和体积;

 通过键盘输入一圆柱体的截面半径(3)和高度(9),输出其表面积和体积;

 将上述输入和输出数据以文本形式保存至当前目录下的一个磁盘文件中。

——输出格式如下:


1)三角形数据

其顶点坐标为:

其周长为:

其面积为:


2)正方形数据

其边长为:

其周长为:

其面积为:


3)长方形数据

其边长为:

其周长为:

其面积为:


4)梯形坝体数据

其梯形顶点坐标为:

其坝体长度为:

其表面积为:

其体积为:


5)圆柱体数据

其截面半径为:

其柱体高度为:

其表面积为:

其体积为:


思路


首先厘清各个类之间的关系,确定继承和派生关系。为了建立一个公共的SHAPE类接口,使它们能够更有效地发挥多态特性,可以将 SHAPE 类作为抽象基类,将计算周长、面积、表面积和体积的函数设为虚函数,在派生类中根据需要对虚函数进行重定义。


如果对抽象基类不太熟悉,可以参考下面的博客:

【C++之纯虚函数与抽象类1】圆形、矩形、三角形的面积


为使程序整洁,我主要定义三角形、正方形、长方形、梯形和圆柱体的数据计算函数以及信息展示函数。根据输入数据的不同,设计周长、面积、表面积和体积的计算公式。


除了设计各种形状的类,完成相应数据计算,本题还需要从键盘输入各个形状原始数据,并将计算结果输出至磁盘文件中。


如果对标准输入输出流或文件流不太熟悉,可以参考下面的博客:

【C++之标准输入输出流】 判断是否符合条件并计算三角形的面积

【C++之文件与文件流】f1.dat 和 f2.dat 文件的读写


程序


/*
*************************************************************************
@file:    T5.cpp
@date:   2021.1.20
@author: Xiaoxiao
@brief:   多层继承和抽象基类的综合应用项目
@blog:    https://blog.csdn.net/weixin_43470383/article/details/112905064
*************************************************************************
*/
#include <iostream>
#include<fstream>
#include <math.h>
using namespace std;
// 形状
class SHAPE 
{
public:
  virtual float Perimeter() { return 0.0; } // 虚函数:计算周长
  virtual float Area() { return 0.0; } // 虚函数:计算面积
  virtual float Surface_area() { return 0.0; } // 虚函数:计算表面积
  virtual float Volume() { return 0.0; } // 虚函数:计算体积
};
// 点
class POINT :public SHAPE 
{
public:
  POINT() { px = 0; py = 0; }
  POINT(int x, int y) :px(x), py(y) {}; // 构造函数
  int px;
  int py;
};
// 直线
class LINE :public POINT 
{
public:
  LINE() { }
  LINE(POINT x, POINT y) :pt1(x), pt2(y) {}; // 构造函数
  float Length(POINT x, POINT y)
  {
  return sqrt(pow((x.px - y.px), 2) + pow((x.py - y.py), 2));
  }
  POINT pt1;
  POINT pt2;
};
// 三角形
class TRIANGLE :public LINE 
{
public:
  TRIANGLE(){}
  TRIANGLE(POINT x, POINT y, POINT z) :a(x), b(y), c(z) {}; // 定义构造函数
  virtual float Perimeter(POINT x, POINT y, POINT z) // 对虚函数再定义
  {
  return Length(a, b) + Length(b, c) + Length(a, c);
  }
  virtual float Area(POINT x, POINT y, POINT z) // 对虚函数再定义
  {
  return (1.0 / 4) * pow((Length(a, b) + Length(b, c) + Length(a, c))*(Length(a, b) + Length(b, c) - Length(a, c))
    *(Length(a, b) + Length(a, c) - Length(b, c))*(Length(b, c) + Length(a, c) - Length(a, b)), 0.5);
  }
  POINT a;
  POINT b;
  POINT c;
};
// 棱柱体
class PRISMOID :public TRIANGLE 
{
public:
  PRISMOID(POINT x, POINT y, POINT z, int he) :TRIANGLE(x, y, z),height(he){}; // 定义构造函数
  POINT a;
  POINT b;
  POINT c;
  int height;
};
// 四边形
class QUADRANGLE :public LINE 
{
public:
  QUADRANGLE() {}
  QUADRANGLE(POINT w, POINT x, POINT y, POINT z) :a(w), b(x), c(y), d(z) {}; // 定义构造函数
  POINT a;
  POINT b;
  POINT c;
  POINT d;
};
// 正方形
class SQUARE :public QUADRANGLE 
{
public:
  SQUARE() {};
  SQUARE(int a) :len(a){}; // 定义构造函数
  virtual float Perimeter(int a) // 对虚函数再定义
  {
  return 4 * a;
  }
  virtual float Area(int a) // 对虚函数再定义
  {
  return a * a;
  }
  int len;
};
// 正方体
class CUBE :public SQUARE 
{
public:
  CUBE() {}
  CUBE(POINT w, POINT x, POINT y, POINT z) :a(w), b(x), c(y), d(z) {}; // 定义构造函数
  POINT a;
  POINT b;
  POINT c;
  POINT d;
}; 
// 长方形
class RECTANGLE :public QUADRANGLE 
{
public:
  RECTANGLE() {};
  RECTANGLE(int a, int b) :height(a), width(b) {}; // 定义构造函数
  virtual float Perimeter(int a, int b) // 对虚函数再定义
  {
  return 2 * (a + b);
  }
  virtual float Area(int a, int b) // 对虚函数再定义
  {
  return a * b;
  }
  int width;
  int height;
};
// 长方体
class CUBOID :public RECTANGLE 
{
public:
  CUBOID() {}
  CUBOID(POINT w, POINT x, POINT y, POINT z) :a(w), b(x), c(y), d(z) {}; // 定义构造函数
  POINT a;
  POINT b;
  POINT c;
  POINT d;
};
// 梯形
class TRAPEZOID :public QUADRANGLE 
{
public:
  TRAPEZOID() {};
  TRAPEZOID(POINT w, POINT x, POINT y, POINT z) :QUADRANGLE(w, x, y, z) {}; // 定义构造函数
  virtual float Area(POINT a, POINT b, POINT c, POINT d) // 对虚函数再定义
  {
  return (Length(a,d)+Length(b, c))*(b.py-a.py)/2; // 注意顺序
  }
  POINT a;
  POINT b;
  POINT c;
  POINT d;
};
// 坝体
class DAM :public TRAPEZOID 
{
public:
  DAM(POINT w, POINT x, POINT y, POINT z, int len) :a(w), b(x), c(y), d(z), length(len) {}; // 定义构造函数
  virtual float Surface_area(POINT w, POINT x, POINT y, POINT z, int len) // 对虚函数再定义
  {
  return 2 * Area(w, x, y, z) + Length(w, x)*len + Length(y, z) * len + Length(w, z) * len + Length(x, y) * len;
  }
  virtual float Volume(POINT w, POINT x, POINT y, POINT z, int len) // 对虚函数再定义
  {
  return len * Area(w, x, y, z);
  }
  POINT a;
  POINT b;
  POINT c;
  POINT d;
  int length;
};
// 曲线
class CURVE :public POINT 
{
public:
  CURVE() { }
};
// 圆形
class CIRCLE :public CURVE 
{
public:
  CIRCLE() { }
  CIRCLE(int r) :radius(r) {}; // 定义构造函数
  virtual float Area(int r) // 对虚函数再定义
  {
  return 3.14159 * r * r;
  }
  int radius;
}; 
// 圆柱体
class CYLINDER :public CIRCLE 
{
public:
  CYLINDER(int r, int h) :radius(r) ,height(h) {}; // 定义构造函数
  virtual float Surface_area(int r, int h) // 对虚函数再定义
  {
  return 2 * Area(r) + 2 * 3.14159 * r * h ;
  }
  virtual float Volume(int r, int h) // 对虚函数再定义
  {
  return Area(r) * h;
  }
  int radius;
  int height;
};
int main()
{
  fstream outfile; // 定义文件流对象
  outfile.open("f1.dat", ios::out); // f1.dat 为输出文件
  if (!outfile)
  {
  cerr << "f1.dat open error!" << endl; // 检查打开 f1.dat 是否成功
  exit(1);
  }
  // 三角形顶点
  POINT pt1, pt2, pt3;
  cout << "输入三角形顶点坐标" << endl;
  cout << "输入第一个顶点的坐标:" << endl;;
  cin >> pt1.px >> pt1.py;
  cout << "输入第二个顶点的坐标:" << endl;;
  cin >> pt2.px >> pt2.py; 
  cout << "输入第三个顶点的坐标:" << endl;;
  cin >> pt3.px >> pt3.py; 
  // 正方形边长
  int length1;
  cout << "输入正方形的边长" << endl;
  cin >> length1;
  // 长方形边长
  int height, width;
  cout << "输入长方形的高" << endl;
  cin >> height;
  cout << "输入长方形的宽" << endl;
  cin >> width;
  // 梯形坝体顶点和长度
  POINT pt4, pt5, pt6, pt7;
  int length2;
  cout << "输入梯形顶点坐标" << endl;
  cout << "输入第一个顶点的坐标:" << endl;;
  cin >> pt4.px >> pt4.py;
  cout << "输入第二个顶点的坐标:" << endl;;
  cin >> pt5.px >> pt5.py;
  cout << "输入第三个顶点的坐标:" << endl;;
  cin >> pt6.px >> pt6.py;
  cout << "输入第四个顶点的坐标:" << endl;;
  cin >> pt7.px >> pt7.py;
  cout << "输入梯形坝体的长度" << endl;
  cin >> length2;
  // 圆柱体截面半径和柱体高度
  int radius, height2;
  cout << "输入圆柱体截面半径" << endl;
  cin >> radius;
  cout << "输入圆柱体柱体高度" << endl;
  cin >> height2;
  // 定义三角形、正方形、长方形、梯形对象
  TRIANGLE triangle(pt1, pt2, pt3);
  SQUARE square(length1);
  RECTANGLE rectangle(height, width);
  DAM dam(pt4, pt5, pt6, pt7, length2);
  CYLINDER cylinder(radius, height2);
  outfile << "1)三角形数据" << endl;
  outfile << "其顶点坐标为:" << "(" << pt1.px << "," << pt1.py << ") "
    << "(" << pt2.px << "," << pt2.py << ") " << "(" << pt3.px << "," << pt3.py << ")" << endl;
  outfile << "其周长为:" << triangle.Perimeter(pt1, pt2, pt3) << endl;
  outfile << "其面积为:" << triangle.Area(pt1, pt2, pt3) << endl << endl;
  outfile << "2)正方形数据" << endl;
  outfile << "其边长为:" << length1 << endl;
  outfile << "其周长为:" << square.Perimeter(length1) << endl;
  outfile << "其面积为:" << square.Area(length1) << endl << endl;
  outfile << "3)长方形数据" << endl;
  outfile << "其边长为:" << height << ", " << width << endl;
  outfile << "其周长为:" << rectangle.Perimeter(height, width) << endl;
  outfile << "其面积为:" << rectangle.Area(height, width) << endl << endl;
  outfile << "4)梯形坝体数据" << endl;
  outfile << "其梯形顶点坐标为:" << "(" << pt4.px << "," << pt4.py << ") " << "(" << pt5.px << "," << pt5.py << ") "
  << "(" << pt6.px << "," << pt6.py << ") " << "(" << pt7.px << "," << pt7.py << ")" << endl;
  outfile << "其坝体长度为:" << length2 << endl;
  outfile << "其表面积为:" << dam.Surface_area(pt4, pt5, pt6, pt7, length2) << endl;
  outfile << "其体积为:" << dam.Volume(pt4, pt5, pt6, pt7, length2) << endl << endl;
  outfile << "5)圆柱体数据" << endl;
  outfile << "其截面半径为:" << radius << endl;
  outfile << "其柱体高度为:" << height << endl;
  outfile << "其表面积为:" << cylinder.Surface_area(radius, height) << endl;
  outfile << "其体积为:" << cylinder.Volume(radius, height) << endl << endl;
  return 0;
}


运行结果


从键盘输入原始数据:




关闭运行窗口,数据被输入到 f1.dat 中。


相关文章
|
8天前
|
存储 并行计算 安全
C++多线程应用
【10月更文挑战第29天】C++ 中的多线程应用广泛,常见场景包括并行计算、网络编程中的并发服务器和图形用户界面(GUI)应用。通过多线程可以显著提升计算速度和响应能力。示例代码展示了如何使用 `pthread` 库创建和管理线程。注意事项包括数据同步与互斥、线程间通信和线程安全的类设计,以确保程序的正确性和稳定性。
|
1月前
|
安全 程序员 编译器
【C++篇】继承之韵:解构编程奥义,领略面向对象的至高法则
【C++篇】继承之韵:解构编程奥义,领略面向对象的至高法则
75 11
|
29天前
|
C++
C++番外篇——对于继承中子类与父类对象同时定义其析构顺序的探究
C++番外篇——对于继承中子类与父类对象同时定义其析构顺序的探究
51 1
|
29天前
|
C++
C++番外篇——虚拟继承解决数据冗余和二义性的原理
C++番外篇——虚拟继承解决数据冗余和二义性的原理
35 1
|
1月前
|
存储 编译器 C++
【C++篇】揭开 C++ STL list 容器的神秘面纱:从底层设计到高效应用的全景解析(附源码)
【C++篇】揭开 C++ STL list 容器的神秘面纱:从底层设计到高效应用的全景解析(附源码)
47 2
|
2月前
|
编译器 C++
【C++核心】函数的应用和提高详解
这篇文章详细讲解了C++函数的定义、调用、值传递、常见样式、声明、分文件编写以及函数提高的内容,包括函数默认参数、占位参数、重载等高级用法。
22 3
|
22天前
|
安全 编译器 程序员
C++的忠实粉丝-继承的热情(1)
C++的忠实粉丝-继承的热情(1)
14 0
|
29天前
|
编译器 C++
C++入门11——详解C++继承(菱形继承与虚拟继承)-2
C++入门11——详解C++继承(菱形继承与虚拟继承)-2
27 0
|
29天前
|
程序员 C++
C++入门11——详解C++继承(菱形继承与虚拟继承)-1
C++入门11——详解C++继承(菱形继承与虚拟继承)-1
31 0
|
2月前
|
C++
C++(二十)继承
本文介绍了C++中的继承特性,包括公有、保护和私有继承,并解释了虚继承的作用。通过示例展示了派生类如何从基类继承属性和方法,并保持自身的独特性。此外,还详细说明了派生类构造函数的语法格式及构造顺序,提供了具体的代码示例帮助理解。