在阅读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 Base
18 {};

可这样一来就要引入虚表了——有一个析构虚函数。为什么必须要有它呢?因为Base要用于派生。《Effective C++》第14条曰:总让base class拥有virtual destructor,因为经由基类指针删除子类对象时,基类如果没有虚析构函数,结果将是未定义。于是定义虚析构函数,于是引入虚表。LightRefBase对象的开销本来只有一个int32_t那么大,引入虚表,空间开销就double啦,大大得不划算。因此采用了CRTP模式,算是场景二的变种。

转载于:https://www.cnblogs.com/palance/p/5194164.html

关于CRTP(Curiously Recurring Template Prattern)的使用相关推荐

  1. 奇异递归模板模式(Curiously Recurring Template Pattern,CRTP)

    The Curiously Recurring Template Pattern (CRTP) is a C++ idiom whose name was coined by James Coplie ...

  2. 计算机编程英文术语,计算机编程英语词汇

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 containment 包容 context 环境.上下文 control 控件 cookie (不译) copy 拷贝 CORBA 通用对象请求中介架构 ...

  3. 计算机编程英语用语,计算机编程英语词汇

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 containment 包容 context 环境.上下文 control 控件 cookie (不译) copy 拷贝 CORBA 通用对象请求中介架构 ...

  4. IT英语2-编程词汇编程英语词汇

    IT英语2-编程词汇编程英语词汇 A2A integration A2A整合  abstract 抽象的  abstract base class (ABC)抽象基类  abstract class ...

  5. 计算机编程学英语词汇,计算机编程英语词汇大全

    index 复合索引.组合索引 (for database) composite key 复合键.组合键 (for database) composition 复合.组合 41.concept 概念 ...

  6. 【转】软件开发常用术语

    软件开发技术常用术语 A.I. 人工智能 A2A integration A2A整合 abstract 抽象的 abstract base class (ABC)抽象基类 abstract class ...

  7. Java基础常见英语词汇

    "ctrl+F"输入关键字来查找 第一章: JDK(Java Development Kit) java开发工具包 JVM(Java Virtual Machine) java虚拟 ...

  8. 计算机常用英语单词对照

    第一部分.计算机算法常用术语中英对照 Data Structures 基本数据结构 Dictionaries 字典 Priority Queues 堆 Graph Data Structures 图 ...

  9. Java英语单词(5000个)

    Java基础常见英语词汇 OO:  面向对象 OOP: object-oriented programming,面向对象编程 JDK:Java development kit, java开发工具包 J ...

最新文章

  1. Java项目:进销存系统(java+Gui)
  2. AC日记——最大子段和 洛谷 P1115
  3. GUID和INT两种数据类型做主键的比较
  4. hive python脚本,Hive调用Python脚本错误
  5. [Apache]安装中出现的问题
  6. mongodb的条件查询笔记
  7. c#编程指南(十二) 平台调用P-INVOKE完全掌握, 结构体边界对齐和内存布局
  8. Android 数据库 在使用 update更新的时候,总是无法更新,还没有异常抛出!
  9. CloudStack 4.4学习总结之注册ISO
  10. Redis集群原理详解
  11. 使用pthread后,界面假死现象问题
  12. 保研面试/考研复试英语口语常见问题整理
  13. css实现半圆(上下左右半圆)
  14. “日历提醒app”程序说明文档
  15. 根据Magic Number(幻数)判断文件类型
  16. linux动态库注册函数,linux下加载动态库函数
  17. python写对象提供的方法_下面哪些是python读对象提供的“写”方法?
  18. OCR开源库Tesseract汉字识别训练
  19. 较好的应用计算机,电脑跑分软件哪个好用?哪个比较权威?电脑跑分软件排行榜2017年...
  20. 磁盘管理1(磁盘碎片、磁盘格式转换)

热门文章

  1. 使用sublime编译运行C程序
  2. 如何用python做计算_如何运用Python编写简易计算器?
  3. 微计算机应用 官网,按照影响因子,查找与计算机通信与技术专业相关的权威期刊...
  4. mysql 存储过程 互斥_mysql中的存储过程和事务隔离
  5. HALCON标定倾斜安装镜头
  6. c++ 包络谱分析代码_基于特征分析谱估计算法(Capon, MUSIC, ESPRIT)的C++实现
  7. 《effective java》类和对象
  8. 理解LSTM/RNN中的Attention机制
  9. 莫比乌斯函数+莫比乌斯反演
  10. linux bash基础