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

时间:2014-05-18 02:24:17

标签: c++ unique-ptr

当一个类具有Base类的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()))
    {

    }
};

然而,它感觉不太对,是吗?

2 个答案:

答案 0 :(得分:2)

如果需要以多态方式进行复制,则需要在所持类型的界面中提供。将clone虚拟函数添加到Base并使用该函数创建副本,您可以将其存储在复制的Foo中。

其他替代方法包括不复制(删除复制构造函数)或使用引用语义(复制引用相同的对象:unique_ptr更改shared_ptr)但这两种选择都不提供副本

答案 1 :(得分:2)

以下是David回答的代码。请注意,this answer中描述了虚拟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.
    {

    }
};