curiously recurring template pattern(CRTP) 奇怪的递归模板模型

名字含义

字面的意思就是派生类名作为继承的模板的参数,形成了一种奇怪的递归。这个名字是由James O. Coplien提出来的,感兴趣的可以看一下原文(Curiously Recurring Template Patterns,但作者所写的FSM机制用的是抽象基类)。笔者认为,CRTP主要还是运用于静态多态。更多的可以翻墙看一下wiki

主要用途

主要应用于要进行扩展的代码(大型代码分开写为了便于维护),而对此又要顾及效率问题。
如果实现算法仅仅是一种,且并不需要额外的扩展,那么就没有必要提及多态的运用(包括动态或者静态的多态),仅仅按照最简单的构建类就可以了。
例如可以把数据放在一个基类,把实现放在派生类。实现这样的情况可以有两种方法。

  1. 使用抽象基类,则运用同样的数据,然后运用相同的接口来进行不同派生类的方法实现,但此时就会构建虚函数表。
  2. 如果为了避免使用虚函数表,则就可以运用静态多态,构建一个继承于数据基类的接口基类模板,然后运用派生类继承接口基类模板来进行方法实现,此时就没有用到虚函数表,从而效率会有很大程度的提高,但也会造成编译时间过长,代码膨胀的缺点。

动态多态运行时造成消耗的原因

  1. 虚函数表,调用虚方法时要额外的指针解除引用
  2. 虚函数无法内联,对于小方法是个损耗
  3. 每个对象都要附加指针。如果是小对象,是个大损耗

实现方式

方法一(仅作为事例)

template <class T> 
class Base {
public:
    void interface() {
        // ...
        static_cast<T*>(this)->implementation();//向下转换指针类型进行调用
        // ...
    }

    static void static_func()  {
        // ...
        T::static_sub_func();
        // ...
    }
};

class Derived : Base<Derived> {
public:
    void implementation();
    static void static_sub_func();
};

方法二(仅作为示例)

template <typename Implementation>
class CRTPInterface {
public:
  void tick(uint64_t n) {
    impl().tick(n);
  }

  uint64_t getvalue() {
    return impl().getvalue();
  }
private:
  Implementation& impl() {
    return *static_cast<Implementation*>(this);//把类型转换放在私有部分,调用部分在公有实现
  }
};

class CRTPImplementation : public CRTPInterface<CRTPImplementation> {
  uint64_t counter;
public:
  CRTPImplementation()
    : counter(0) {
  }

  void tick(uint64_t n) {
    counter += n;
  }

  uint64_t getvalue() {
    return counter;
  }
};

参考

  1. The Curiously Recurring Template Pattern in C++ ,Eli Bendersky’s website
  2. The cost of dynamic (virtual calls) vs. static (CRTP) dispatch in C++,Eli Bendersky’s website
  3. 奇异递归模板模式( Curiously Recurring Template Pattern,CRTP)1,DanielWang_
  4. 关于c++ template多态——CRTP 模式
  5. C++: Polymorphic cloning and the CRTP (Curiously Recurring Template Pattern),Katy
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值