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

如何拷贝指向未知派生类的unique_ptr的内容?

如何拷贝持有无资源抽象基类的std::unique_ptr<Base>?

你遇到的是典型的多态拷贝问题——因为std::unique_ptr<Base>指向的是派生类对象,但编译器只知道基类的接口,直接拷贝指针只会触发「对象切片」,无法完整复制派生类的内容。好在你的类都不管理资源,我们只需要给类体系添加一套克隆机制就能解决问题。

先看你的原始代码:

#include <memory>
#include <vector>
// 这是一个不包含资源的纯抽象类
class Base {
public:
    Base() {};
    virtual int doSomething() = 0;
};
class Derived : public Base {
public:
    Derived() {};
    // 此方法会修改派生类
    int doSomething() override { return 0; };
};
class Derived2 : public Base {
public:
    Derived2() {};
    // 此方法会修改派生类
    int doSomething() override { return 1; };
};

解决方案:添加多态克隆方法

这是C++中实现多态拷贝的标准做法,步骤很简单:

1. 在基类中声明纯虚clone方法

给Base类新增一个返回std::unique_ptr<Base>的纯虚函数,作为克隆的入口:

class Base {
public:
    Base() = default;
    // 纯虚克隆方法,要求所有派生类必须实现
    virtual std::unique_ptr<Base> clone() const = 0;
    virtual int doSomething() = 0;
    // 因为类无资源,默认析构足够(若有资源则需要虚析构)
    virtual ~Base() = default;
};

2. 在每个派生类中实现clone

每个派生类需要重写clone方法,返回自身对象的拷贝:

class Derived : public Base {
public:
    Derived() = default;
    int doSomething() override { return 0; };
    // 克隆当前Derived对象,包装成Base指针返回
    std::unique_ptr<Base> clone() const override {
        return std::make_unique<Derived>(*this);
    }
};

class Derived2 : public Base {
public:
    Derived2() = default;
    int doSomething() override { return 1; };
    std::unique_ptr<Base> clone() const override {
        return std::make_unique<Derived2>(*this);
    }
};

3. 使用clone完成拷贝

现在你可以通过调用clone方法,轻松拷贝unique_ptr<Base>指向的任意派生类对象:

#include <iostream>

int main() {
    std::unique_ptr<Base> ptr1 = std::make_unique<Derived>();
    // 拷贝ptr1指向的Derived对象
    std::unique_ptr<Base> ptr2 = ptr1->clone();
    
    std::unique_ptr<Base> ptr3 = std::make_unique<Derived2>();
    std::unique_ptr<Base> ptr4 = ptr3->clone();
    
    std::cout << ptr1->doSomething() << std::endl; // 输出0
    std::cout << ptr2->doSomething() << std::endl; // 输出0(拷贝成功)
    std::cout << ptr3->doSomething() << std::endl; // 输出1
    std::cout << ptr4->doSomething() << std::endl; // 输出1(拷贝成功)
    
    return 0;
}

为什么这个方案可行?

  • clone是虚函数,调用时会根据指针实际指向的派生类类型,执行对应的实现逻辑
  • std::make_unique<Derived>(*this)会利用编译器生成的默认拷贝构造函数,完整复制当前派生类对象,再包装成unique_ptr<Base>返回,完美实现多态拷贝
  • 因为你的类都不管理资源,不需要手动编写拷贝构造/析构函数,编译器生成的默认版本就足够用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:09:18