4

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

在其他一些类中,我们希望有一个 type 的成员shared_ptr<Base>

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

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

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

这种方法的问题在于,这需要每个新的子类Base来实现这个clone()功能。每个中的代码都clone()相当样板,一直重复它似乎有点不自然。

自 C++11 以来有更好的方法来做到这一点吗?

4

1 回答 1

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 改进这一点:您可以使用(但您会失去协变返回类型),您可以制作privateunique_ptr<base>的析构函数并使用.base_implfriend T

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

  • 许多分层的层次结构并不常见
  • 克隆函数不是很有用
  • 然而,该设计是可扩展的并且超越了克隆:使用模板作为自动化样板代码的一种方式在例如。ATL 和 WTL。搜索“奇怪地重复出现的模板模式”。

另一种解决方案。这可能可以通过各种方式改进,但我认为你不能避免有两个克隆功能:

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)); }
};
于 2012-12-16T00:18:59.047 回答