具有基类唯一ptr的类的复制构造函数

Copy constructor for a class that has unique ptr of a Base class

本文关键字:构造函数 复制 ptr 基类 唯一      更新时间:2023-10-16

当类具有基类的unique_ptr时,实现复制构造函数的好方法是什么?

让我试着用一个例子来解释:

struct Base
{
    virtual void doSth() = 0; // to make the class abstract.
};
struct Derived : public Base
{
    virtual void doSth() override {}
};
struct Foo
{
    std::unique_ptr<Base> bar;
    Foo(const Foo& other) : bar(new Base(*other.bar))   // cant do it, its abstract.
    {
        bar = std::move(other.bar); // cant do it, reference object is modified.
    }
};

由于类是抽象的,所以不能使用它的复制构造函数。也不能在常量引用上使用move(我们实际上不应该这样做,不要修改对象)。

结果是这样的:

struct Base
{
    virtual void doSth() = 0; // to make the class abstract.
};
struct Derived : public Base
{
    virtual void doSth() override {}
    Derived(const Base* b)
    {
    }
};
struct Foo
{
    std::unique_ptr<Base> bar;
    Foo(const Foo& other) : bar(new Derived(other.bar.get()))
    {
    }
};

但是,感觉不太对,不是吗?

如果需要进行多态复制,则需要在所持有的类型的接口中提供这一点。向Base添加一个clone虚拟函数,并使用它来创建一个副本,您可以将其存储在复制的Foo中。

其他替代方法包括不复制(删除复制构造函数)或使用引用语义(副本指向同一个对象:将unique_ptr更改为shared_ptr),但这些替代方法都没有真正提供副本

下面是David回答的代码。请注意,这个回答中描述了虚拟clone()

#include <stdlib.h>
#include <cstddef>
#include <memory>

struct Base
{
   virtual void doSth() = 0; // to make the class abstract.
   virtual Base* clone() const = 0;
};
struct Derived : public Base
{
    virtual void doSth() override {}
    virtual Derived* clone() const {
        return new Derived(*this);
    }
};
struct Foo
{
    std::unique_ptr<Base> bar;
    Foo(const Foo& other) : bar(other.bar->clone())   // cant do it, its abstract.
    {
    }
};