【问题标题】:How To Make a clone method using shared_ptr and inheriting from enable_shared_from_this如何使用 shared_ptr 并从 enable_shared_from_this 继承来创建克隆方法
【发布时间】:2010-09-07 02:35:17
【问题描述】:

我已经看到编写一个返回 boost::shared_ptr 的克隆方法的有用方法是这样做

class A
{
public:
  shared_ptr<A> Clone() const
  {
    return(shared_ptr<A>(CloneImpl()));
  }
protected:
  virtual A* CloneImpl() const
  {
    return(new A(*this));
  }
};

class B : public A
{
public:
  shared_ptr<B> Clone() const
  {
    return(shared_ptr<B>(CloneImpl()));
  }
protected:
  virtual B* CloneImpl() const
  {
    return(new B(*this));
  }
};

这允许使用与常规指针的协方差,同时仍将其包装在智能指针的安全性中。我的问题是我的 B 类需要从 boost::enable_shared_from_this 继承,因为在构造之后它需要立即向一个单独的类注册自己,并将一个共享指针传递给它自己。我有一个包装构造和注册的 Create 方法,以确保它们总是一起发生。然而,上面的克隆方法实现不能处理这个要求。注册不能在 CloneImpl 中发生,因为尚不存在“拥有”该对象的 shared_ptr,从而阻止了对 shared_from_this() 的调用,并且如果此逻辑不在虚函数中,则指向 B 的 shared_ptr 不知道 B 的注册需求克隆时。处理这个问题的最佳方法是什么?

【问题讨论】:

  • 这段代码能编译吗?看起来 B::Clone() 隐藏了 A::Clone()。
  • 这个例子是为我编译的。我相信 B::Clone() 隐藏 A::Clone() 是有目的的,以便您获得正确的返回类型。

标签: c++ shared-ptr


【解决方案1】:

由于您已经通过非虚拟 Clone() 函数自己实现了 public 接口协方差,因此您可以考虑放弃 CloneImpl() 函数的协方差。

如果您只需要 shared_ptr 而不需要原始指针,那么您可以这样做:

class X
{
public:
  shared_ptr<X> Clone() const
  {
    return CloneImpl();
  }
private:
  virtual shared_ptr<X> CloneImpl() const
  {
    return(shared_ptr<X>(new X(*this)));
  }
};

class Y : public X
{
public:
  shared_ptr<Y> Clone() const
  {
    return(static_pointer_cast<Y, X>(CloneImpl())); // no need for dynamic_pointer_cast
  }
private:
  virtual shared_ptr<X> CloneImpl() const
  {
    return shared_ptr<Y>(new Y(*this));
  }
};

CloneImpl() 将始终返回 shared_ptr&lt;Base&gt;,现在您可以在 B::CloneImpl() 函数中注册您的对象并返回注册的 shared_ptr。

【讨论】:

  • 谢谢我相信这很好地解决了问题。事实上,即使忽略注册要求,这种克隆方法看起来是不是比我列出的更好,这是我在使用智能指针进行克隆时经常看到的示例?此版本似乎提供了相同的功能,同时消除了对我列出的 CloneImpl 中创建的常规指针的任何可能滥用。
  • @user334066 - 我想这取决于。我发布的示例可以在 boost 邮件列表档案中找到。您的 Clone 函数允许在类内部使用原始指针,这有时可能有意义。
猜你喜欢
  • 2019-01-15
  • 2015-03-24
  • 2011-04-26
  • 1970-01-01
  • 2011-05-28
  • 1970-01-01
  • 2013-04-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多