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

C++中Zoo类拷贝构造函数无法保留派生类对象的问题求助

解决多态对象的深拷贝问题

你的问题核心是对象切片:直接调用基类Animal的拷贝构造函数时,只会拷贝基类部分,丢失派生类的特有数据和类型信息。要保留派生类类型,需要用克隆模式(Clone Pattern),通过虚函数实现动态绑定的拷贝。

步骤1:在基类Animal中添加纯虚clone函数

首先在Animal类中声明一个纯虚的clone方法,强制所有派生类实现自己的拷贝逻辑:

class Animal {
public:
    // 其他成员变量和方法...
    
    // 纯虚克隆函数,返回当前对象的深拷贝
    virtual Animal* clone() const = 0;
    
    // 必须添加虚析构函数,避免内存泄漏
    virtual ~Animal() = default;
};

步骤2:在每个派生类中实现clone方法

每个派生类(如Horse、Flamingo)都要重写clone函数,返回自身的深拷贝。C++支持协变返回类型,可以直接返回派生类指针:

// Horse类示例
class Horse : public Animal {
public:
    // 派生类的成员变量和方法...
    
    // 重写clone,返回Horse对象的拷贝
    Horse* clone() const override {
        return new Horse(*this);
    }
};

// Flamingo类示例
class Flamingo : public Animal {
public:
    // 派生类的成员变量和方法...
    
    Flamingo* clone() const override {
        return new Flamingo(*this);
    }
};

步骤3:修改Zoo的拷贝构造函数

将原来直接new Animal的代码,替换为调用clone函数。此时会根据对象的实际类型(派生类)动态调用对应的clone实现,完成完整的深拷贝:

Zoo::Zoo(const Zoo& other)//copy c'tor
{
    m_name = _strdup(other.m_name);
    m_address = _strdup(other.m_address);
    m_ticketPrice = other.m_ticketPrice;
    m_openHours = _strdup(other.m_openHours);
    m_closeHours = _strdup(other.m_closeHours);
    m_numOfAnimals = other.m_numOfAnimals;

    // 深度拷贝动物数组,保留派生类类型
    m_animals = new Animal * [other.m_numOfAnimals];
    for (int i = 0; i < other.m_numOfAnimals; i++)
    {
        // 调用clone函数,动态绑定到派生类的实现
        m_animals[i] = other.m_animals[i]->clone();
    }
}

额外注意事项

  • 虚析构必须存在:如果基类没有虚析构,当你通过Animal*指针删除派生类对象时,只会调用基类析构函数,导致派生类的资源无法释放,引发内存泄漏。
  • 优先使用智能指针:手动管理Animal*数组容易出错,建议改用std::vector<std::unique_ptr<Animal>>存储动物对象。此时clone函数可以返回std::unique_ptr<Animal>,避免手动delete的问题:
    // 基类中修改clone函数
    virtual std::unique_ptr<Animal> clone() const = 0;
    
    // 派生类实现
    std::unique_ptr<Animal> Horse::clone() const override {
        return std::make_unique<Horse>(*this);
    }
    
    // Zoo类中用vector存储
    class Zoo {
    private:
        std::vector<std::unique_ptr<Animal>> m_animals;
        // 其他成员...
    };
    
    // 拷贝构造函数简化为
    Zoo::Zoo(const Zoo& other)
        : m_name(_strdup(other.m_name)),
          m_address(_strdup(other.m_address)),
          m_ticketPrice(other.m_ticketPrice),
          m_openHours(_strdup(other.m_openHours)),
          m_closeHours(_strdup(other.m_closeHours))
    {
        for (const auto& animal : other.m_animals) {
            m_animals.push_back(animal->clone());
        }
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 17:37:30