gpt4 book ai didi

c++ - 从基类指针克隆派生类

转载 作者:行者123 更新时间:2023-12-04 03:41:54 27 4
gpt4 key购买 nike

在我们的遗留项目中,我们有一个函数引用基类并在堆上创建派生类的拷贝。这基本上是这样解决的:https://godbolt.org/z/9ooM4x

#include <iostream>

class Base
{
public:
virtual Base* vclone() const = 0;
int a{7};
};

class Derived : public Base
{
public:
Derived()
{
a = 8;
}

Base* vclone() const override
{
return new Derived(*this);
}
};

Base* clone(const Base& original)
{
return original.vclone();
}

int main()
{
Derived d1;;
auto* d2 = clone(d1);

std::cout << d2->a << std::endl;
}
这可行,但我想摆脱我们在每个派生类中都必须拥有的样板 vclone 方法。
我们有数百个派生类,其中一些不是直接从 Base 派生的,而是从其他一些派生类派生的。因此,如果我们忘记覆盖 vclone 方法,我们甚至可能不会收到将发生切片的警告。
现在,关于这样的设计有很多话要说,但这是 10 到 15 年前的代码,我试图逐步对其进行现代化改造。我正在寻找的是不依赖于虚拟方法的模板化版本的克隆。我想要的是这样的克隆功能:
Base* clone(const Base& original)
{
return new <Actual Derived Type>(original);
}
实际派生类型有点为人所知,因为如果尝试使用错误的类型进行强制转换,dynamic_cast 将失败,但我不知道是否可以以我想要的方式访问实际类型。
任何帮助,将不胜感激。

最佳答案

我还认为您可能无法从某种意义上改进代码以使其更短。
我想说这个实现基本上是要走的路。
您可以做的是更改 Derived::clone 的返回值至Derived * .是的,C++ 允许这样做。
然后直接使用Derived::clone产生正确的指针类型和 Base::clone仍然按预期工作

class Derived : public Base
{
public:
Derived()
{
a = 8;
}

Derived* vclone() const override // <<--- 'Derived' instead of 'Base'.
{
return new Derived(*this);
}
};
我还要重命名为 vclone成员函数到 clone (不需要有两个名字)。
免费功能 clone可以制作一个模板,以便它适用于所有类并返回正确的指针类型
template <class T>
T *clone(const T *cls)
{
return cls->clone();
}
然而,所有这些更改并没有使代码更短,只是更有用,也许更易读。
为了让它更短一点,您可以使用 CRTP 方法。
template <class Derived, class Base>
class CloneHelper: public Base {
Derived* vclone() const override
{
return new Derived(* static_cast<Derived *>(this) );
}
};
// then use
class Derived : public CloneHelper<Derived, Base>
{
public:
Derived()
{
a = 8;
}
};
但是,我不确定这是否值得。仍然不能忘记 CloneHelper , 它使继承总是 public你不能委托(delegate)给 Base构造函数如此简单,而且不那么明确。

关于c++ - 从基类指针克隆派生类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65916601/

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