You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++多态对象数组复制问题:allShapes类+运算符实现遇报错求解决

解决抽象类拷贝与operator+实现的问题

你的问题核心在于抽象类无法直接实例化,同时需要实现多态对象的深拷贝来避免重复析构的问题。下面一步步给你解决思路和代码示例:

为什么会报错?

Shape作为抽象类(包含纯虚函数),编译器不允许直接创建它的对象。你写的new Shape(*_arr[i])试图实例化抽象类,这就是"Object of abstract class are not allowed"错误的原因。

要实现多态对象的深拷贝,我们需要用**虚克隆(Virtual Clone)**的设计模式——给抽象基类添加一个纯虚的clone方法,让每个派生类自己实现拷贝逻辑。

步骤1:给Shape类添加虚clone方法

首先修改你的Shape基类,添加纯虚的clone函数,同时确保析构函数是虚函数(这是多态类的基本要求,否则派生类的析构不会被正确调用):

class Shape {
    // 你的现有成员变量,比如_shapeName、_centerPoint等
protected:
    std::string _shapeName;
    // 假设_centerPoint是某个点类型,比如Point _centerPoint;

public:
    // 纯虚clone方法,强制子类实现
    virtual Shape* clone() const = 0;

    // 虚析构函数,确保派生类析构被调用
    virtual ~Shape() = default;

    // 你的其他虚函数(比如draw()之类的抽象方法)
};

步骤2:在每个派生类中重写clone方法

每个继承自Shape的具体类(Circle、Quad、Square)都要实现clone方法,返回自身的拷贝:

Circle类示例

class Circle : public Shape {
    // Circle的特有成员,比如_radius
private:
    double _radius;

public:
    // 拷贝构造函数(你需要自己实现,拷贝Circle的所有成员)
    Circle(const Circle& other) : Shape(other), _radius(other._radius) {}

    // 重写clone方法,返回Circle的拷贝
    Circle* clone() const override {
        return new Circle(*this);
    }

    // 其他Circle的成员函数...
};

Quad类示例

class Quad : public Shape {
    // Quad的特有成员,比如_sideLength
private:
    double _sideLength;

public:
    Quad(const Quad& other) : Shape(other), _sideLength(other._sideLength) {}

    Quad* clone() const override {
        return new Quad(*this);
    }

    // 其他Quad的成员函数...
};

Square类示例(假设Square继承Quad)

class Square : public Quad {
    // Square的特有成员(如果有的话)

public:
    Square(const Square& other) : Quad(other) {}

    Square* clone() const override {
        return new Square(*this);
    }

    // 其他Square的成员函数...
};

步骤3:修改operator+的实现,使用clone完成深拷贝

现在你可以在operator+中调用clone方法来创建派生类对象的拷贝,而不是直接实例化抽象类:

allShapes allShapes::operator+(const allShapes & other) const {
    allShapes newAllShapes;
    newAllShapes._arr = new Shape *[_size + other._size];
    newAllShapes._size = _size + other._size;

    int i = 0;
    // 拷贝当前对象的所有Shape
    for (; i < _size; i++) {
        newAllShapes._arr[i] = _arr[i]->clone(); // 调用多态的clone
    }
    // 拷贝另一个对象的所有Shape
    for (int j = 0; j < other._size; j++, i++) {
        newAllShapes._arr[i] = other._arr[j]->clone();
    }

    return newAllShapes;
}

额外注意:完善allShapes的拷贝语义

为了避免其他浅拷贝问题,你需要遵循三/五法则,实现allShapes的拷贝构造函数、赋值运算符和析构函数:

析构函数(释放所有Shape对象)

allShapes::~allShapes() {
    for (int i = 0; i < _size; i++) {
        delete _arr[i]; // 因为Shape析构是虚的,会调用派生类的析构
    }
    delete[] _arr;
}

拷贝构造函数

allShapes::allShapes(const allShapes& other) {
    _size = other._size;
    _arr = new Shape*[_size];
    for (int i = 0; i < _size; i++) {
        _arr[i] = other._arr[i]->clone();
    }
}

赋值运算符(使用拷贝交换 idiom)

#include <algorithm> // 用于std::swap

allShapes& allShapes::operator=(allShapes other) {
    // 交换当前对象和临时对象的资源
    std::swap(_arr, other._arr);
    std::swap(_size, other._size);
    return *this;
}

为什么这样可行?

  • clone方法是多态的:当你调用_arr[i]->clone()时,会根据_arr[i]实际指向的对象类型(Circle/Quad/Square)调用对应的clone方法,创建正确的派生类对象,避免了实例化抽象类的问题。
  • 深拷贝:每个Shape对象都被复制了一份,新的allShapes对象拥有独立的Shape指针数组,不会和原对象共享内存,解决了之前析构时多次删除同一对象的问题。

内容的提问来源于stack exchange,提问作者sagi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:08:49