C ++ 11中存储的任何好的新方法,作为成员,“克隆”其他“层次结构类”的对象?

时间:2012-12-16 00:08:28

标签: c++

我们有一个Base类和一个Derived类派生自Base

在其他一些课程中,我们希望拥有shared_ptr<Base>类型的成员。

我们不能直接使用Base类型,因为这样的直接复制将排除子类。

但是,我们仍然希望在构造时“复制”Base(或子类)对象,因为我们想要排除它被修改的可能性。

处理此问题的经典方法是将虚拟成员函数clone()放入Base类中,Base的每个子类都可以实现。然后,每个clone()只返回自己的“副本” - 例如,Derived将返回make_shared<Derived>(*this)

这种方法的问题在于,这需要Base的每个新子类来实现此clone()函数。每个clone()中的代码都是样板文件,并且一直重复它似乎有点不自然。

自C ++ 11以来有更好的方法吗?

1 个答案:

答案 0 :(得分:5)

在普通的C ++中总是可以这样做:

struct base
{
    virtual ~base () {}
    virtual base* clone () = 0;  
    virtual void foo () = 0;
};

template <typename T>
struct base_impl : base
{
    T* clone () { return new T (*static_cast<T*> (this)); }
};

struct derived : base_impl<derived>
{ 
    void foo () { ... }
};

struct derived2 : base_impl<derived2>
{
    void foo () { ...}
};

您可以使用C ++ 11改进这一点:您可以使用unique_ptr<base>(但是您丢失了协变返回类型),您可以将base_impl的析构函数设为私有并使用friend T

我同意在这种情况下这不是很灵活,但是:

  • 许多分层的层次结构并不常见
  • 克隆功能不是很有用
  • 设计仍然是可扩展的并且超越了克隆:使用模板作为自动化样板代码的方法在例如中被彻底使用。 ATL和WTL。搜索&#34;好奇地重现模板模式&#34;。

另一种解决方案。这可能会以各种方式得到改善,但我认为你不能避免使用两种克隆功能:

struct base
{
    std::unique_ptr<base> clone () { return std::unique_ptr<base> (do_clone ()); }

private:
    virtual base *do_clone () = 0;
};

template <typename T>
struct base_impl : base
{
    std::unique_ptr<T> clone () 
    {
        return std::unique_ptr<T> (static_cast<T*> (do_clone ()));
    }    

private:
    base *do_clone () { return new T (*static_cast<T*> (this)); }
};