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
相关产品推荐
相关产品推荐

