我有以下课程:
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();发布于 2017-05-09 06:58:02
实现这一目标的方法是使用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) { ... }
};这三个层次结构是非常常见的。基本上,顶级类和前面一样是纯接口(注意:其他函数也应该=0)。中产阶级使用CRTP模式:它是在派生类型上模板化的。其思想是,通过对派生类型的静态访问,它可以自动实现像Clone这样的东西。然后,派生类型实现任何不能泛化的实现。
请注意,派生的大多数类型继承自CRTP类模板本身。这就是名称的来源(奇怪的是反复出现的模板模式)。当然,由于继承是传递性的,所以B也继承了A的继承,就像最初的那样,启用了相同的东西。
下面是一个可以执行的完整示例:http://coliru.stacked-crooked.com/a/8f2b201a06b5abcc。我尽可能地将代码保存在类似于问题的答案中,但在coliru示例中,有几个很小但很重要的区别:
https://stackoverflow.com/questions/43862981
复制相似问题