纯基 class c++ 动态数组的问题

Trouble with dynamic array of pure base class c++

我有一个介绍 c++ 的编程作业 class。该程序应该使用虚拟函数来输入、计算和显示与各种形状相关的数量。 Shape class 必须包含所有纯虚函数:display、getdimensions、area、perimeter 和 volume。

程序驱动程序必须为 Shape 分配一个包含 20 个指针的数组,然后用输入的对象重复填充该数组。

我的程序在到达显示调用时正在退出。所以我认为这意味着我的 getDimensions 或显示功能无法正常工作。我花了几个小时试图解决这个问题,如果有人能指出正确的方向,我似乎无法找到到底出了什么问题。

这是我的代码:

#include <iostream>
#include <cmath>
using namespace std;

const double PI=3.141592654;

class Shape
{
protected:
    double x, y;
public:
    Shape(): x(1.0),y(1.0){}
    Shape(double a, double b): x(a),y(b){}
    virtual void display()=0;
    virtual void getDimensions()=0;
    virtual double area()=0;
    virtual double perimeter()=0;
   virtual double volume()=0;
};

class Rectangle: public Shape
{
public:
    Rectangle():Shape(){}
    Rectangle(double a, double b):Shape(a,b){}
    void display();
    void getDimensions()
    {
        cout<<"Input for Rectangle - "
            <<"enter length and width: ";
        cin>>x>>y;
    }
    double area()
        {return x*y;}
    double perimeter()
        {return (2*x)+(2*y);}
    double volume()
        {return 0;}
};

class Circle: public Shape
{
private:
    double radius;
public:
    Circle(): radius(1.0){}
    Circle(double r): radius(r){}
    void display();
    void getDimensions()
    {
        cout<<"Input for Circle - enter radius: ";
        cin>>radius;
    }
    double area()
        {return PI*radius*radius;}
    double perimeter()
        {return 2*PI*radius;}
    double volume()
        {return 0;}
 };

class Triangle: public Shape
 {
private:
    double z;
public:
    Triangle():z(1.0), Shape(){}
    Triangle(double f, double g, double w):z(w), Shape(f,g){}
    void display();
    void getDimensions()
    {
        cout<<"Input for Triangle - "
            <<"enter side 1, side 2, side 3: ";
        cin>>x>>y>>z;
    }
    double area()
    {
        double half, underroot;
        half = perimeter()/2;
        underroot = half*(half-x)*(half-y)*(half-z);
        return sqrt(underroot);
    }
    double perimeter()
        {return x+y+z;}
    double volume()
        {return 0;}
};

class Box: public Shape
{
private:
    double p;
public:
    Box():p(1.0), Shape(){}
    Box(double a, double b, double c): Shape(a,b), p(c){}
    void display();
    void getDimensions()
    {
        cout<<"Input for Box - "
            <<"enter length, width, and height: ";
        cin>>x>>y>>p;
    }
    double area()
        {return (2*x*y)+(2*x*p)+(2*y*p);}
    double perimeter()
        {return 0;}
    double volume()
        {return x*y*p;}
};

class Can: public Shape
{
public:
    Can():Shape(){}
    Can(double r, double h):Shape(r,h){}
    void display();
    void getDimensions()
    {
        cout<<"Input for Can - "
            <<"enter radius and height: ";
        cin>>x>>y;
    }
    double area()
    {
        double base;
        base = PI*x*x;
        return (2*PI*x*y)+(2*PI*x*x);
    }
    double perimeter()
        {return 0;}
    double volume()
        {return PI*x*x*y;}
};

class Cone: public Shape
{
public:
    Cone():Shape(){}
    Cone(double r, double h):Shape(r, h){}
    void display();
    void getDimensions()
    {
        cout<<"Input for Cone - "
            <<"enter radius and height: ";
        cin>>x>>y;
    }
    double area()
    {
        double underroot;
        underroot = sqrt((x*x)+(y*y));
        return (PI*x*x)+(PI*x*underroot);
    }
    double perimeter()
        {return 0;}
    double volume()
        {return (1/3)*PI*x*x*y;}
};

class Ball: public Shape
{
private:
    double radius;
public:
    Ball():radius(1.0){}
    Ball(double r):radius(r){}
    void display();
    void getDimensions()
    {
        cout<<"Input for Ball - "
            <<"enter radius: ";
        cin>>radius;
    }
    double area()
        {return 4*PI*radius*radius;}
    double perimeter()
        {return 0;}
    double volume()
        {return (4/3)*PI*radius*radius*radius;}
};

int main()
{
    int cnt=0, cnt2=0, choice;
    char yorn;

    Shape *sPtr[20];

    while(cnt<20)
    {
        cnt++;
        cnt2++;
        cout<<"\nIt is time to enter your shape selection"
            <<" and dimensions.\n"
            <<"Enter the number of the shape type: \n"
            <<"\t1 - Rectangle\n"
            <<"\t2 - Circle\n"
            <<"\t3 - Triangle\n"
            <<"\t4 - Box\n"
            <<"\t5 - Can\n"
            <<"\t6 - Cone\n"
            <<"\t7 - Ball\n"
            <<"=> ";
        cin>>choice;
        while (choice<1||choice>7)
        {
            cout<<"Invalid selection. Re-enter: \n"
                <<"=> ";
            cin>>choice;
        }
        switch (choice)
        {
        case 1:
        {
            sPtr[cnt]=new Rectangle;
            sPtr[cnt]->getDimensions();
            break;
        }
        case 2:
        {
            sPtr[cnt]=new Circle;
            sPtr[cnt]->getDimensions();
            break;
        }
        case 3:
        {
            sPtr[cnt] = new Triangle;
            sPtr[cnt]->getDimensions();
            break;
        }
        case 4:
        {
            sPtr[cnt] = new Box;
            sPtr[cnt]->getDimensions();
            break;
        }
        case 5:
        {
            sPtr[cnt] = new Can;
            sPtr[cnt]->getDimensions();
            break;
        }
        case 6:
        {
            sPtr[cnt] = new Cone;
            sPtr[cnt]->getDimensions();
            break;
        }
        case 7:
        {
            sPtr[cnt] = new Ball;
            sPtr[cnt]->getDimensions();
            break;
        }
        }

        cout<<"\nSelect another shape? (y or n): ";
        cin>>yorn;
        if(yorn=='n'||yorn=='N')
            cnt=20;
    }
    for(int i=0; i<cnt2; i++)
    {
        sPtr[i]->display();
    }
    return 0;
}

void Rectangle::display()
{
    cout<<"\nRectangle: "
        <<"\nDimensions: "
        <<"Length: "<<x<<"\nWidth: "<<y
        <<"\nArea: "<<area()
        <<"\nPerimeter: "<<perimeter();
}

void Circle::display()
{
    cout<<"\nCircle: "
        <<"\nDimensions: "
        <<"\nRadius: "<<radius
        <<"\nArea: "<<area()
        <<"\nPerimeter: "<<perimeter();
}

void Triangle::display()
{
    cout<<"\nTriangle: "
        <<"\nDimensions: "
        <<"\nSide 1: "<<x
        <<"\nSide 2: "<<y
        <<"\nSide 3: "<<z
        <<"\nArea: "<<area()
        <<"\nPerimeter: "<<perimeter();
}

void Box::display()
{
    cout<<"\nBox: "
        <<"\nDimensions: "
        <<"\nLength: "<<x
        <<"\nWidth: "<<y
        <<"\nHeight: "<<p
        <<"\nSurface area: "<<area()
        <<"\nVolume: "<<volume();
}

void Can::display()
{
    cout<<"\nBox: "
        <<"\nDimensions: "
        <<"\nRadius: "<<x
        <<"\nHeight: "<<y
        <<"\nSurface area: "<<area()
        <<"\nVolume: "<<volume();
}

void Cone::display()
{
    cout<<"\nCone: "
        <<"\nDimensions: "
        <<"\nRadius: "<<x
        <<"\nHeight: "<<y
        <<"\nSurface area: "<<area()
        <<"\nVolume: "<<volume();
}

void Ball::display()
{
    cout<<"\nBall: "
        <<"\nDimensions: "
        <<"\nRadius: "<<radius
        <<"\nSurface area: "<<area()
        <<"\nVolume: "<<volume();
}

您从 0:

开始显示
for(int i=0; i<cnt2; i++)
{
    sPtr[i]->display();
}

但是您从 1:

开始添加到 sPtr
int cnt=0;
while(cnt<20)
{
    cnt++;
    ...
    sPtr[cnt] = new ...;
}

这些类型的错误是更喜欢使用 std::vector<Shape*> 而不是原始数组和计数器的重要原因。那么你可以只写下面的,这样不容易出错:

std::vector<Shape*> shapes;
while (shapes.size() < 20) {
    ...
    shapes.push_back(new Rectangle);
    ...
}

for (size_t i = 0; i < shapes.size(); ++i) { 
    shapes[i]->display();
}

或者实际上,在 C++11 中,这应该是 vector<unique_ptr<Shape>>