【问题标题】:C++ "'Shape': cannot instantiate abstract class" can't find the source of the problemC++“'Shape': 无法实例化抽象类”找不到问题的根源
【发布时间】:2025-12-04 14:20:16
【问题描述】:

我有 5 个不同的类(在不同的文件中)从它继承的 Shape 类。 在覆盖所有不同类中的所有纯虚函数后,我收到此错误: '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);
    }

如果有人能帮我找到问题,我会很高兴。

【问题讨论】:

  • 您在哪里创建对象?您没有发布实际发生错误的相关部分。
  • 你尝试只编译 Shape 吗?之后尝试只编译多边形。这可以给出一个提示。
  • 你有没有尝试过实例化一个 Polygon ?请注意,如果您不实现它们,则不需要在 Polygon 中重新声明纯虚拟函数。另请注意,您可以在您覆盖的函数上使用 [覆盖说明符](v)。
  • @ChrisMM 我在帖子中添加了更多代码,以便了解更多
  • @0xBlackMirror 错误出现在哪一行?

标签: c++ inheritance overriding abstract-class multiple-inheritance


【解决方案1】:

您不能将对象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;

【讨论】:

  • 用向量绑定对象的生命周期会更符合最初的意图:使用std::vector&lt;std::unique_ptr&lt;Shape&gt;&gt;而不是裸指针。
  • 谢谢,这实际上可以编译。但是我会在传递局部变量时遇到问题,因为它们会在超出范围时被破坏。
  • @MichaelDoubez 好点。我添加了示例。希望我写得正确(没有测试任何东西)。
  • 哦,我刚刚写过,你编辑过,谢谢!
最近更新 更多