我们有一个Base
类和一个Derived
类派生自Base
。
在其他一些课程中,我们希望拥有shared_ptr<Base>
类型的成员。
我们不能直接使用Base
类型,因为这样的直接复制将排除子类。
但是,我们仍然希望在构造时“复制”Base
(或子类)对象,因为我们想要排除它被修改的可能性。
处理此问题的经典方法是将虚拟成员函数clone()
放入Base
类中,Base
的每个子类都可以实现。然后,每个clone()
只返回自己的“副本” - 例如,Derived
将返回make_shared<Derived>(*this)
。
这种方法的问题在于,这需要Base
的每个新子类来实现此clone()
函数。每个clone()
中的代码都是样板文件,并且一直重复它似乎有点不自然。
自C ++ 11以来有更好的方法吗?
答案 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
我同意在这种情况下这不是很灵活,但是:
另一种解决方案。这可能会以各种方式得到改善,但我认为你不能避免使用两种克隆功能:
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)); }
};