小工具知识网

当前位置: 首页 > 行业知识 > C++惯用法之CRTP(奇异递归模板模式)

行业知识

C++惯用法之CRTP(奇异递归模板模式)

2026-10-19 08:31:34 来源:互联网转载

���关系列文章

()

如何写出高质量的函数?快来学习这些coding技巧

C++惯用法之Pimpl

()

C++之数据转换(全)

目录

1.介绍

2.CRTP的使用场景

2.1.实现静态多态

2.2.代码复用和扩展性

3.总结


1.介绍

        CRTP的全称是Curiously Recurring Template Pattern,即奇异递归模板模式,简称CRTP。CRTP是一种特殊的模板技术和使用方式,是C++模板编程中的一种惯用法。基本特征表现为:基类是一个模板类;派生类在继承该基类时,将派生类自身作为模板参数传递给基类。下面用网上的实例来说明为什么要用CRTP? 比如我要实现一个数学库,如果使用运行时多态来实现向量类Vector,那么代码结构大致如下:

templatestruct VectorBase{    virtual void someFunction(){...}    ...};struct Vector3: VectorBase{    virtual void someFunction() override {...}};

         需要注意的是,运行时多态是有开销的,熟悉c++虚函数的人应该就能明白,如果我调用一个虚函数,需要查询对象头部的虚函数表来得到实际函数地址,这个寻址的开销对于一个数学库而言是非常巨大的。而如果使用静态多态,则可以使用如下的代码来实现:

template  struct VectorBase {  ChildType &underlying() { return static_cast(*this); }  inline ChildType &operator+=(const ChildType &rhs) {    this->underlying() = this->underlying() + rhs;    return this->underlying();  }};struct Vec3f : public VectorBase {  float x{}, y{}, z{};  Vec3f() = default;  Vec3f(float x, float y, float z) : x(x), y(y), z(z) {}};inline Vec3f operator+(const Vec3f &lhs, const Vec3f &rhs) {  Vec3f result;  result.x = lhs.x + rhs.x;  result.y = lhs.y + rhs.y;  result.z = lhs.z + rhs.z;  return result;}

        可以看到,静态多态虽然导致代码复用度相较于运行时多态降低了很多,但是相较于完全手写,我们可以利用子类实现的operator+来通过CRTP自动添加operator+=,相当于是做到了运行效率与开发效率的相对平衡。 

        VectorBase是模版基类,派生类Vec3f 继承自VectorBase,并以自身作为模板参数传递给基类, 在基类内部,通过使用static_cast,将this指针转换为模板参数类型T的指针,然后调用类型T的方法imp。static_cast的用法可参考一下博客。

C++之数据转换(全)_c++数据类型转换-CSDN博客

2.CRTP的使用场景

2.1.实现静态多态

C ++支持动态和静态多态。

  • 动态多态性:在这种类型的多态性中,在编译时不知道对象的类型(可能基于用户输入等),因此编译器添加了额外的数据结构来支持这一点。 该标准并未规定应如何实施。C++通过虚函数表实现多态,但是虚函数会影响类的内存布局,并且虚函数的调用会增加运行时的开销。
  • 静态多态性:在这种类型中,对象的类型在编译时本身是已知的,因此实际上无需在数据结构中保存额外的信息。 但是如前所述,我们需要在编译时知道对象的类型。

    CRTP 可以实现静态多态,但本质上 CRTP 中的多个派生类并不是同一个基类,因此严格意义上不能叫多态。示例如下:

    templateclass base{public:    virtual ~base(){}    void interface() { static_cast(this)->impl(); }    void impl() { cout 

上一篇:方舟如何进别人服务器?

下一篇:本地服务器怎么联机使用?