gpt4 book ai didi

c++ - 从具有模板返回值的函数中删除类型

转载 作者:IT老高 更新时间:2023-10-28 22:39:07 25 4
gpt4 key购买 nike

我有以下类(class):

class A {
public:
virtual std::string Serialize();
virtual void Deserialize(std::string);

template <typename T>
T* Clone()
{
std::string s = Serialize();
T* t = new T();
t->Deserialize(s);
return t;
}
};

class B : public A {
public:
std::string Serialize() { ... }
void Deserialize(std::string) { ... }
};

现在,如果我想克隆 B,我执行以下操作:

B b1;
B* b2 = b1.Clone<B>();

有没有什么方法可以移除模板类型而不需要在每个派生类中重新实现Clone

我想要这样的东西:

B b1;
B* b2 = b1.Clone();

最佳答案

使用 CRTP 的方法是:

class A {
public:
virtual std::string Serialize();
virtual void Deserialize(std::string);
virtual A* Clone() = 0;
};

template <class T>
class HelperA : public A {

T* Clone() override
{
std::string s = Serialize();
T* t = new T();
t->Deserialize(s);
return t;
}
};

class B : public HelperA<B> {
public:
std::string Serialize() { ... }
void Deserialize(std::string) { ... }
};

这 3 级层次结构很常见。基本上,顶级类是纯接口(interface),和以前一样(注意:其他函数也应该 = 0)。中间类使用 CRTP 模式:它是在派生类型上模板化的。这个想法是,通过对派生类型的静态访问,它可以自动实现像 Clone 这样的东西。然后派生类型实现任何一般无法完成的实现。

请注意,派生最多的类型继承自以自身为模板的 CRTP 类。这就是名称的由来(Curiously Recurring Template Pattern)。当然,由于继承是可传递的,B 也从 A 继承,仍然和原来一样,可以实现相同的功能。

这是一个完整的工作示例,您可以执行:http://coliru.stacked-crooked.com/a/8f2b201a06b5abcc .我将答案中的代码尽可能地与问题相似,但在 coliru 示例中存在一些小但重要的区别:

  • 在 C++ 中使用拥有指针而不是原始指针被认为是一种很好的做法,并且由于智能指针不是协变的,这会影响签名
  • 正确使用 = 0 和覆盖,以及 const
  • 静态向下转换的示例,它是 CRTP 的一种签名,但您的示例没有提出

关于c++ - 从具有模板返回值的函数中删除类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43862981/

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