关于CRTP(Curiously Recurring Template Prattern)的使用
来源:互联网 发布:2016年淘宝数据分析 编辑:程序博客网 时间:2024/05/21 16:00
在阅读frameworks/rs/cpp/util/RefBase.h之LightRefBase时,我记得《C++设计新思维》里对这种用法是有过介绍的,可是今天翻箱倒柜,怎么都找不到那本奇书了。当年所谓的前卫,今天已经遍地开花,赶紧再把CRTP给复习一下。
CRTP模式主要有两种使用场景:
- 一、Meyers Counting
template <typename T>class Counting{public: Counting() { mCount++; } ~Counting() { mCount--; } static int mCount;};template <typename T> int Counting<T>::mCount = 0;class CountedA : public Counting<CountedA>{};class CountedB : public Counting<CountedB>{};
CountedA类和CountedB类都具备了引用计数功能,这是从Counting基类派生下来的,但是引用计数具体的数值是每个子类各自维护,这主要是拜mCount的static属性所赐,Counting<CountedA>和Counting<CountedB>是不同的类,也就有不同的静态成员。
不过LightRefBase显然不是这种应用场景。
- 二、用编译时绑定替代运行时绑定,避免虚表的时空性能开销。
#include "stdafx.h"#include <stdio.h>template <typename T>class Fucker{public: void doFuck() { printf("Failed :(\n"); } void Fuck() { ((T*)this)->doFuck(); }};class AFucker : public Fucker<AFucker>{};class BFucker : public Fucker<BFucker>{public: void doFuck() { printf("Shuang :)\n"); }};int main(int argc, char** argv){ Fucker<BFucker>* pFucker = new BFucker(); pFucker->Fuck(); return 0;}
上面,Fuck()和doFuck()共同完成了虚函数的表演,但无需承担虚表的开销。乍一看LightRefBase也不是这种设计,因为它显然没有虚函数的桥段。
1 template <class T> 2 class LightRefBase 3 { 4 public: 5 inline LightRefBase() : mCount(0) { } 6 inline void incStrong(__attribute__((unused)) const void* id) const { 7 __sync_fetch_and_add(&mCount, 1); 8 } 9 inline void decStrong(__attribute__((unused)) const void* id) const {10 if (__sync_fetch_and_sub(&mCount, 1) == 1) {11 delete static_cast<const T*>(this);12 }13 }14 //! DEBUGGING ONLY: Get current strong ref count.15 inline int32_t getStrongCount() const {16 return mCount;17 }18 19 typedef LightRefBase<T> basetype;20 21 protected:22 inline ~LightRefBase() { }23 24 private:25 friend class ReferenceMover;26 inline static void moveReferences(void*, void const*, size_t,27 const ReferenceConverterBase&) { }28 29 private:30 mutable volatile int32_t mCount;31 };
它唯一使用了模板参数的地方就是#11,可以断定此处就是该设计的初衷。如果用派生的方式,也可以完成这个任务:
1 class Base 2 { 3 public: 4 Base() :mCount(0) {} 5 int IncRef() { return ++mCount; } 6 int DecRef() { 7 if (--mCount <= 0) { 8 delete this; 9 }10 return mCount;11 }12 virtual ~Base() {}13 private:14 int mCount;15 };16 17 class Derived : public Base18 {};
可这样一来就要引入虚表了——有一个析构虚函数。为什么必须要有它呢?因为Base要用于派生。《Effective C++》第14条曰:总让base class拥有virtual destructor,因为经由基类指针删除子类对象时,基类如果没有虚析构函数,结果将是未定义。于是定义虚析构函数,于是引入虚表。LightRefBase对象的开销本来只有一个int32_t那么大,引入虚表,空间开销就double啦,大大得不划算。因此采用了CRTP模式,算是场景二的变种。
0 0
- 关于CRTP(Curiously Recurring Template Prattern)的使用
- 奇异递归模板模式(Curiously Recurring Template Pattern,CRTP)
- C++惯用法:奇特的递归模板模式(Curiously Recurring Template Pattern,CRTP,Mixin-from-above)
- C++惯用法:奇特的递归模板模式(Curiously Recurring Template Pattern,CRTP,Mixin-from-above)
- C++惯用法:奇特的递归模板模式(Curiously Recurring Template Pattern,CRTP,Mixin-from-above)
- C++惯用法:奇特的递归模板模式(Curiously Recurring Template Pattern,CRTP,Mixin-from-above)
- 奇异递归模板模式( Curiously Recurring Template Pattern,CRTP)1
- curiously recurring template pattern
- Curiously Recurring Template
- Curiously Recurring Template Pattern
- Curiously recurring template pattern (zz)
- 递归模板模式--The curiously recurring template pattern
- 关于c++ template多态——CRTP 模式
- 关于template的使用
- 使用CRTP做更好的封装
- 使用CRTP做更好的封装
- 奇异递归模板模式(CRTP)应用--表达式模板(expression template) 2
- 关于template的用法
- 写一个Android输入法01——最简步骤
- mac下面自带svn客户端的使用方法
- 写一个Android输入法02——候选窗、转换
- article元素
- Android源码、内核编译
- 关于CRTP(Curiously Recurring Template Prattern)的使用
- 工欲善其事——Sublime Text
- 实现内核驱动程序模块
- Android开发之Intent跳转到系统应用中的拨号界面、联系人界面、短信界面
- 海啸的数学模型
- android碰见的问题(1)
- Hibernate之Hibernate与触发器协调使用
- 【字符串处理算法】回文判断的算法设计及C代码实现
- instancetype、id、NSObject的区别