C ++ «Shape»: не может создать экземпляр абстрактного класса »не может найти источник проблемы - PullRequest
0 голосов
/ 30 ноября 2019

У меня есть класс Shape, который наследуется от 5 разных классов (в разных файлах). После переопределения всех чисто виртуальных функций во всех различных классах я получаю эту ошибку: 'Shape': cannot instantiate abstract class, и она не скажет мне, где ошибка. Это Shape класс:

#pragma once
#include "Point.h"
#include "Canvas.h"
#include <string>

class Shape 
{
public:
    Shape(const std::string& name, const std::string& type);
    virtual double getArea() const = 0;
    virtual double getPerimeter() const = 0;
    virtual void draw(const Canvas& canvas) = 0;
    virtual void move(const Point& other) = 0; // add the Point to all the points of shape
    void printDetails() const;
    std::string getType() const;
    std::string getName() const;

    virtual void clearDraw(const Canvas& canvas) = 0;

protected:
    std::string _name;
    std::string _type;
};

, и вот пример 2 классов, которые наследуются от Shape:

class Circle : public Shape
{
    Point _center;
    double _radius;

public:
    Circle(const Point& center, double radius, const std::string& type, const std::string& name);
    ~Circle();

    const Point& getCenter() const;
    double getRadius() const;

    virtual void draw(const Canvas& canvas);
    virtual void clearDraw(const Canvas& canvas);

    // override functions if need (virtual + pure virtual)
    virtual void move(const Point& other);
    virtual double getArea() const;
    virtual double getPerimeter() const;
};

И я подозреваю, что проблема заключается в этомкласс, и в этом классе я сохраняю функции чисто виртуальными, потому что от этого класса наследуются и другие классы, и им нужна другая реализация:

#include "Shape.h"
#include "Point.h"
#include <vector>

class Polygon : public Shape
{
public:
    Polygon(const std::string& type, const std::string& name);
    virtual ~Polygon();

    // override functions if need (virtual + pure virtual)
    virtual void move(const Point& other);
    virtual double getArea() const = 0;
    virtual double getPerimeter() const = 0;
    virtual void draw(const Canvas& canvas) = 0;
    virtual void clearDraw(const Canvas& canvas) = 0;

protected:
    std::vector<Point> _points;
};

Вот часть кода, в которой, я думаю,может произойти ошибка:

if (optionChosen == 0) // Circle
    {
        double x = 0;
        double y = 0;
        double radius = 1.0;
        std::string name;

        std::cout << "Please enter X: " << std::endl;
        std::cin >> x;
        std::cout << "Please enter Y: " << std::endl;
        std::cin >> y;

        do
        {
            std::cout << "Please enter radius: " << std::endl;
            std::cin >> radius;
            if (radius < 1)
            {
                std::cout << "Invalid radius... Try again" << std::endl;
            }
            // If radius is invalid this code will run again
        } while (radius < 1);

        std::cout << "Enter the name of the shape: " << std::endl;
        std::cin >> name;

        const Point& center = Point(x, y);
        // Create a new circle and push it to the vector
        Circle circle = Circle::Circle(center, radius, "Circle", name); // Circle inherits from Shape
        _shapes.push_back(circle);
    }
    else if (optionChosen == 1) // Arrow
    {
        double point1[2] = { 0 };
        double point2[2] = { 0 };

        std::string name;

        std::cout << "Enter the X of point number: 1" << std::endl;
        std::cin >> point1[0];
        std::cout << "Enter the Y of point number: 1" << std::endl;
        std::cin >> point1[1];
        std::cout << "Enter the X of point number: 2" << std::endl;
        std::cin >> point2[0];
        std::cout << "Enter the Y of point number: 2" << std::endl;
        std::cin >> point2[1];

        std::cout << "Enter the name of the shape: " << std::endl;
        std::cin >> name;

        const Point& Point1 = Point(point1[0], point1[1]);
        const Point& Point2 = Point(point2[0], point2[1]);
        // Create a new arrow and push it to the vector
        Arrow arrow = Arrow::Arrow(Point1, Point2, "Arrow", name); // Arrow inherits from polygon
        _shapes.push_back(arrow);
    }
    else if (optionChosen == 2) // Triangle
    {
        double point1[2] = { 0 };
        double point2[2] = { 0 };
        double point3[2] = { 0 };

        std::string name;

        std::cout << "Enter the X of point number: 1" << std::endl;
        std::cin >> point1[0];
        std::cout << "Enter the Y of point number: 1" << std::endl;
        std::cin >> point1[1];
        std::cout << "Enter the X of point number: 2" << std::endl;
        std::cin >> point2[0];
        std::cout << "Enter the Y of point number: 2" << std::endl;
        std::cin >> point2[1];
        std::cout << "Enter the X of point number: 3" << std::endl;
        std::cin >> point3[0];
        std::cout << "Enter the Y of point number: 3" << std::endl;
        std::cin >> point3[1];

        std::cout << "Enter the name of the shape: " << std::endl;
        std::cin >> name;

        const Point& Point1 = Point(point1[0], point1[1]);
        const Point& Point2 = Point(point2[0], point2[1]);
        const Point& Point3 = Point(point3[0], point3[1]);
        // Create a new triangle and push it to the vector
        Triangle triangle = Triangle::Triangle(Point1, Point2, Point3, "Triangle", name); // Triangle inherits from Polygon
        _shapes.push_back(triangle);
    }
    else if (optionChosen == 3) // Rectangle
    {
        double topLeftCorner[2] = { 0 };
        double length = 0;
        double width = 0;

        std::string name;

        std::cout << "Enter the X of the left corner: " << std::endl;
        std::cin >> topLeftCorner[0];
        std::cout << "Enter the Y of the left corner: " << std::endl;
        std::cin >> topLeftCorner[1];
        std::cout << "Please enter the length of the shape: " << std::endl;
        std::cin >> length;
        std::cout << "Please enter the width of the shape: " << std::endl;
        std::cin >> width;
        std::cout << "Enter the name of the shape: " << std::endl;
        std::cin >> name;

        const Point& point = Point(topLeftCorner[0], topLeftCorner[1]);
        // Create a new rectangle and push it to the vector
        myShapes::Rectangle rectangle = myShapes::Rectangle(point, length, width, "Rectangle", name); // Rectangle inherits from Polygon
        _shapes.push_back(rectangle);
    }

Если кто-нибудь поможет мне найти проблему, я буду очень счастлив.

1 Ответ

3 голосов
/ 01 декабря 2019

Вы не можете сохранить объект Shape в векторе, так как он содержит чисто виртуальную функцию. Вместо этого вы можете хранить указатели в векторе или интеллектуальные указатели и соответствующим образом создавать дочерние классы.

std::vector<Shape*> _shapes;
//…
_shapes.push_back( new Circle( … ) );

или

std::vector<std::unique_ptr<Shape>> _shapes;
//…
_shapes.push_back( std::make_unique<Circle>( center, radius, "Circle", name ) );

Кроме того, при использовании наследования я бы рекомендовал использоватьключевое слово override. Так, например, в вашем классе Circle у вас будет

void move(const Point& other) override;
...