//设计一个计算图形面积的类库。
//类库的顶层是一个抽象类Shape,并且提供三个纯虚函数;显示数据成员、返回面积和返回体积。
//由Shape类派生Shape2D(二维图形)和Shape3D(三维图形),增加了有关的数据成员
//派生具体的图形类。
//Shape2D类派生Circle(圆)、Rectangle(矩形)。
//Shape3D类派生Ball(球体)、Cylinder(圆柱体)。
//在主函数测试中使用多态方式调用不同对象的求值函数。

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
using namespace std;
const double PI = 3.1415926;

//创建一个抽象类
class Shape
{
    virtual ~Shape(){}
    virtual void showData() = 0;    //数据成员
    virtual double reArea() = 0;    //返回面积
    virtual double reVolume() = 0;  //返回体积
};

// 2D 图形
class Shape2D :public Shape
{
protected:
    double x, y;    // 2个成员
public:
    virtual void showData() { }
    virtual double reArea() { return 0;}
    virtual double reVolume() { return 0; }
};

// 3D 图形
class Shape3D :public Shape
{
protected:
    double x, y, z; // 3个成员
public:
    virtual void showData() { }
    virtual double reArea() { return 0; }
    virtual double reVolume() { return 0; }
};

// 圆形
class Circle :public Shape2D
{
public:
    Circle(double tp) {
        x = tp; //r
    }
    Circle(Circle &asp) {
        x = asp.x;
    }

    void showData() {
        cout << " a Circle:" << endl
            << "The radiation:" << x << endl
            << "The area:" << reArea() << endl;
    }
    double reArea() {
        return PI*x*x;
    }
};

// 方形
class Rectangle :public Shape2D {
public:
    Rectangle(double ta, double tb) {
        x = ta, y = tb;
    }
    Rectangle(Rectangle &asp) {
        x = asp.x, y = asp.y;
    }

    void showData() {
        cout << " a Rectangle:" << endl
            << "The long axis:" << x << endl
            << "The short axis:" << y << endl
            << "The area:" << reArea() << endl;
    }
    double reArea() {
        return x*y;
    }
};

// 球体
class Ball :public Shape3D {
public:
    Ball(double ta) {
        x = ta;
    }
    Ball(Ball &asp) {
        x = asp.x;
    }

public:
    void showData() {
        cout << "This is a Ball:" << endl
            << "The radiation:" << x << endl
            << "The surface area:" << reArea() << endl;
    }
    double reVolume() {
        return PI*pow(x, 3)*4.0 / 3.0;
    }
    double reArea() {
        return PI*x*x;
    }
};

// 圆柱体
class Cylinder :public Shape3D {
public:
    //V=PI*r*r*h    S=2*PI*r+r*h
    Cylinder(double ta, double tb) {
        x = ta; //r
        y = tb; //h
    }
    Cylinder(Cylinder &asp) {
        x = asp.x;
        y = asp.y;
    }

    void showData() {
        cout << "This is a Cylinder:" << endl
            << "The radiation:" << x << endl
            << "The height:" << y << endl
            << "The surface area:" << reArea() << endl;
    }
    double reArea() {
        return 2 * PI*x + x*y;
    }
    double reVolume() {
        return PI*x*x*y;
    }
};

int main(void) {
    Shape2D a;
    Shape3D b;
    Shape2D *p = &a;
    Shape3D *w = &b;

    Circle      t1(1.0);
    Rectangle   t3(10.0, 2.3);
    Ball        t5(2.33333);
    Cylinder    t6(4.5, 65.0);

    p = &t1;    p->showData();
    p = &t3;    p->showData();
    w = &t5;    w->showData();
    w = &t6;    w->showData();

    // 暂停
    system("pause");
    return EXIT_SUCCESS;
}