行业知识
C++惯用法之CRTP(奇异递归模板模式)
���关系列文章
()如何写出高质量的函数?快来学习这些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
上一篇:方舟如何进别人服务器?
下一篇:本地服务器怎么联机使用?