首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用模板返回值从函数中删除类型

使用模板返回值从函数中删除类型
EN

Stack Overflow用户
提问于 2017-05-09 06:50:24
回答 1查看 565关注 0票数 14

我有以下课程:

代码语言:javascript
复制
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,我做以下操作:

代码语言:javascript
复制
B b1;
B* b2 = b1.Clone<B>();

在每个派生类中,是否有任何方法可以删除模板类型而不重新实现Clone

我想要这样的东西:

代码语言:javascript
复制
B b1;
B* b2 = b1.Clone();
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-05-09 06:58:02

实现这一目标的方法是使用CRTP:

代码语言:javascript
复制
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示例中,有几个很小但很重要的区别:

  • 在C++中,拥有指针而不是原始指针的使用被认为是一个很好的实践,而且由于智能指针不是协变的,这会影响签名。
  • 正确使用=0和覆盖,以及const
  • 静态下播的一个例子,它是CRTP的一个签名,它没有给出您的示例
票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43862981

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档