gpt4 book ai didi

c++ - 防止为每个子类编写克隆方法

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:39:02 24 4
gpt4 key购买 nike

这是我的案例:

class A
{
public:
virtual A* clone() = 0;
};

class B : public A
{
virtual B* clone() override
{
return new B();
}
};

在我的代码中,现在 100% 的 A 子类都以完全相同的方式实现 clone 方法,仅对类 D 我已经返回键入 D,我当然会创建 D 的对象。

如何防止这种重复?哪些模式或技巧可以提供帮助?

我想过使用CRTP pattern ,但它使用模板,我的功能是虚拟的。据我们了解,模板和虚函数是不兼容的。

NVI pattern也不起作用,因为克隆方法的返回类型不同。

最佳答案

[class.virtual]/8:

If the class type in the covariant return type of D::f differs from that of B::f, the class type in the return type of D::f shall be complete at the point of declaration of D::f or shall be the class type D.

因此 CRTP 不能完美地工作,因为引用派生类的模板参数将是一个不完整的类型,因此协变返回类型很难模拟。

但是,这里有一个尝试:

class A
{
public:
virtual A* clone() = 0;
};

namespace detail {
template <typename T>
struct Cloner : A {
using A::A; // For constructors
virtual A* clone() override {return new T;}
};
}

template <typename T>
struct Cloner : detail::Cloner<T> {
using detail::Cloner<T>::Cloner; // For constructors

// For callers
template <class=void>
T* clone() {return static_cast<T*>(detail::Cloner<T>::clone());}
};

class B : public Cloner<B>
{
};

Demo .

注意两点:

  • clone 的重载返回一个指向派生类类型的指针是一个函数模板。这样我们就不会重写虚函数 clone:如果我们重写,代码将是错误的,因为返回类型不是协变的(见上文)。

  • 因为clone是一个函数模板,为了确保它被调用,我们可以让它隐藏虚拟的clone函数。这是通过继承实现的:派生类中的名称隐藏了基类中的名称。因此,如果我们通过 B 指针/引用进行调用,我们将获得适当的返回类型 (B*),因为名称是在 ::Cloner 中查找的detail::Cloner 之前。

关于c++ - 防止为每个子类编写克隆方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28524398/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com