是否有可能有一个复制可构造的类,它包含一个std :: unique_ptr <Base>避免切片而没有Base暴露一个"克隆"函数?

rub*_*nvb 1 smart-pointers deep-copy copy-constructor move-semantics c++11

有没有办法为类编写一个拷贝构造函数(比如说Copyable,它可以保存std::unique_ptr一个Base类(但实际上是存储Derived对象).

快速测试显示预期的切片发生,因为Copyable不知道它所持有的实际类型.所以我想一个clone方法是必要的,但我想知道是否有办法让编译器以更好的方式处理它?

切片代码:

#include <algorithm>
#include <iostream>
#include <memory>
struct Base
{
  Base(int i = 0) : i(i) {}
  virtual ~Base() = default;
  int i;
  virtual int f() { return i; }
};

struct Derived : Base
{
  Derived() = default;
  virtual int f() override { return 42; }
};

struct Copyable
{
  Copyable(std::unique_ptr<Base>&& base) : data(std::move(base)) {}
  Copyable(const Copyable& other)
  {
    data = std::make_unique<Base>(*other.data);
  }
  std::unique_ptr<Base> data;
};

int main()
{
  Copyable c(std::make_unique<Derived>());
  Copyable c_copy = c;

  std::cout << c_copy.data->f() << '\n';
}
Run Code Online (Sandbox Code Playgroud)

clone代码:

#include <algorithm>
#include <iostream>
#include <memory>
struct Base
{
  Base(int i = 0) : i(i) {}
  virtual ~Base() = default;
  int i;
  virtual int f() { return i; }

  virtual Base* clone() { return new Base(i); }
};

struct Derived : Base
{
  Derived() = default;
  virtual int f() override { return 42; }

  virtual Derived* clone() override { return new Derived(); }

};

struct Copyable
{
  Copyable(std::unique_ptr<Base>&& base) : data(std::move(base)) {}
  Copyable(const Copyable& other)
  {
    data.reset(other.data->clone());
  }
  std::unique_ptr<Base> data;
};

int main()
{
  Copyable c(std::make_unique<Derived>());
  Copyable c_copy = c;

  std::cout << c_copy.data->f() << '\n';
}
Run Code Online (Sandbox Code Playgroud)

显然克隆代码有效.事情是,我想避免一些事情:

  1. 生的new.
  2. 一个随机函数,需要成为接口的一部分.
  3. 此函数返回原始指针.
  4. 此类的每个想要可复制的用户都需要调用此函数.

那么,有一个"干净"的选择吗?

注意我想使用智能指针,原因很明显,我只需要深度复制std::unique_ptr.类似于std::copyable_unique_ptr,将可选的移动语义与深度复制复制构造函数相结合.这是最干净的方式吗?或者这只会增加混乱?

Ded*_*tor 5

您当然可以clone_ptr为静态知道如何克隆的任何对象创建一个类.

它将保存指向对象的指针,以及指向克隆所述对象的函数的指针,可能来自转换无状态lambda.