(C++) 如何为具有唯一指针作为数据成员的 class 编写克隆方法?

(C++) How to write a clone method for a class which has a unique pointer as a data member?

我有以下设置:

class Base {
private:
// data members
public:
// methods
// pure virtual methods
virtual Base* clone() const =0;
}

class Derived : public Base{
private:
// more data members
public:
// more methods
// pure virtual methods overridden
Derived* clone() const override{
return new Derived(*this);
}

我现在想介绍一个新的派生 class,在装饰器模式的上下文中,它有一个指向 Base class 对象作为数据成员的唯一指针。我的问题是如何正确实现 clone() 方法,因为“标准”实现会导致编译时错误,因为无法复制唯一指针:

class DecoratedDerived : public Base{
private:
unique_ptr<Base> ptr;
// more data members
public:
// more methods
// pure virtual methods overridden
DecoratedDerived* clone() const override{
return new DecoratedDerived(*this); // compiler error
}

一个解决方案是在克隆方法中构造一个新的 DecoratedDerived class 对象(通过显式深度复制与当前对象关联的所有成员),然后将指针传递给它。但是,如果 class 有很多其他成员,这将非常耗时。

我还应该说我只使用了一个唯一指针,因为这似乎是现代 C++ 中使用的标准智能指针。特别是在我使用 C+11 之前,我刚刚设计了我自己的智能指针,它负责所有的内存管理等,因此对于那种类型的智能指针,装饰 [=23= 中的克隆方法不会有问题].

在此先感谢您的帮助!

这是可能的实现,当新的 DecoratedDerived 被构造时,成员项目也被克隆:

class Base {
   public:
    virtual std::unique_ptr<Base> clone() const = 0;
};

class Empty : public Base {
   public:
    std::unique_ptr<Base> clone() const override {
        return std::make_unique<Empty>();
    }
};

class DecoratedDerived : public Base {
   private:
    std::unique_ptr<Base> ptr;

   public:
    DecoratedDerived() : ptr{std::make_unique<Empty>()} {}

    DecoratedDerived(std::unique_ptr<Base> wrap) : ptr{std::move(wrap)} {}

    std::unique_ptr<Base> clone() const override {
        return std::make_unique<DecoratedDerived>(ptr->clone());
    }
};

https://godbolt.org/z/sG3zTehb1

Empty class 是避免检查 nullptr.

的好方法

另请注意,因为您正在使用 unique_ptr 我已经在其他地方介绍了它们,当它看起来合乎逻辑时。

只需向 DecoratedDerived 添加一个复制构造函数,即 clone() 的数据成员,例如:

class DecoratedDerived : public Base {
private:
    unique_ptr<Base> ptr;
    // ...
public:
    DecoratedDerived(const DecoratedDerived &src)
        : Base(src), ptr(src.ptr ? src.ptr->clone() : nullptr)
    {
    }

    // ...

    DecoratedDerived* clone() const override{
        return new DecoratedDerived(*this);
    }
};

Online Demo