奇异递归模板模式(Curiously Recurring Template Pattern)

2024-09-04 05:28

本文主要是介绍奇异递归模板模式(Curiously Recurring Template Pattern),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

奇异递归模板模式(Curiously Recurring Template Pattern) - 知乎 (zhihu.com)

本文来自上面的文章!!!本菜鸡学习和记录一下。

CRTP是C++模板编程时的一种惯用法:把派生类作为基类的模板参数。

1.静态多态

#include <iostream>
using namespace std;template <typename Child>
struct Base
{void interface(){static_cast<Child*>(this)->implementation();}
};struct Derived : Base<Derived>
{void implementation(){cerr << "Derived implementation\n";}
};struct test : Base<test>
{void implementation(){cerr << "test\n";}
};int main()
{Derived d;d.interface();  // Prints "Derived implementation"test t;t.interface();return 0;
}

基类为Base,是模板类,子类Drived继承自Base同时模板参数为Drived,基类中有接口

interface而子类中有接口对应实现implementation,基类interface中将this通过static_cast转换为模板参数类型,这里是Drived,并调用该类型的implemention方法。

为什么是static_cast,而不是dynamic_cast?

因为只有继承了Base的类型才能调用interface且这里是向下转型,所以采用static_cast是安全的。

(不太理解)

通过CRTP可以使得类具有类似于虚函数的效果,同时没有虚函数调用时的开销(虚函数调用时需要通过虚函数指针查找虚函数表进行调用),同时类的对象的体积相比使用虚函数也会减少(不需要存储虚函数指针),但是缺点是无法动态绑定。

2.

template<typename Child>
class Animal
{
public:void Run(){static_cast<Child*>(this)->Run();}
};class Dog :public Animal<Dog>
{
public:void Run(){cout << "Dog Run" << endl;}
};class Cat :public Animal<Cat>
{
public:void Run(){cout << "Cat Run" << endl;}
};template<typename T>
void Action(Animal<T> &animal)
{animal.Run();
}int main()
{Dog dog;Action(dog);Cat cat;Action(cat);return 0;
}

Dog继承自Animal且模板参数为Dog,Cat继承自Animal且模板参数为Cat

Animal,Dog,Cat中都声明了Run,Animal中的Run是通过类型转换后调用模板类型的Run方法实现的。在Action模板参数中接收Animal类型的引用(或指针)并在其中调用了animal对象的Run方法,由于这里传入的是不同的子类对象,因此Action中的animal也会有不同的行为。

3.添加方法,减少冗余

//Vec3
struct Vector3
{float x;float y;float z;Vector3() = default;Vector3(float _x, float _y, float _z);inline Vector3& operator+=(const Vector3& rhs);inline Vector3& operator-=(const Vector3& rhs);//....
};inline Vector3 operator+(const Vector3& lhs, const Vector3& rhs);
inline Vector3 operator-(const Vector3& lhs, const Vector3& rhs);
//....//Vec2
struct Vector2
{float x;float y;Vector2() = default;Vector2(float _x, float _y);inline Vector2& operator+=(const Vector2& rhs);inline Vector2& operator-=(const Vector2& rhs);//....
};inline Vector2 operator+(const Vector2& lhs, const Vector2& rhs);
inline Vector2 operator-(const Vector2& lhs, const Vector2& rhs);
//....

 类型Vector3需要实现+=,-=,+,-等运算符重载。

 类型Vector2需要实现+=,-=,+,-等运算符重载。

其中+=,-=这两个运算符可以采取+,-运算符实现,这时候可以把+=,-=给抽象出来,减少代码冗余。

template<typename T>
struct VectorBase
{T& underlying() { return static_cast<T&>(*this); }T const& underlying() const { return static_cast<T const&>(*this); }inline T& operator+=(const T& rhs) { this->underlying() = this->underlying() + rhs;return this->underlying();}inline T& operator-=(const T& rhs){this->underlying() = this->underlying() - rhs;return this->underlying();}//.....
};struct Vector3 : public VectorBase<Vector3>
{float x;float y;float z;Vector3() = default;Vector3(float _x, float _y, float _z){x = _x;y = _y;z = _z;}
};inline Vector3 operator+(const Vector3& lhs, const Vector3& rhs)
{Vector3 result;result.x = lhs.x + rhs.x;result.y = lhs.y + rhs.y;result.z = lhs.z + rhs.z;return result;
}inline Vector3 operator-(const Vector3& lhs, const Vector3& rhs)
{Vector3 result;result.x = lhs.x - rhs.x;result.y = lhs.y - rhs.y;result.z = lhs.z - rhs.z;return result;
}
//......int main()
{Vector3 v0(6.0f, 5.0f, 4.0f);Vector3 v2(4.0f, 5.0f, 6.0f);v0 += v2;v0 -= v2;return 0;
}

在VectorBase中实现了+=,-=

它们依赖子类的+和-运算符的实现。

这篇关于奇异递归模板模式(Curiously Recurring Template Pattern)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1135115

相关文章

Java利用Spire.Doc for Java实现在模板的基础上创建Word文档

《Java利用Spire.DocforJava实现在模板的基础上创建Word文档》在日常开发中,我们经常需要根据特定数据动态生成Word文档,本文将深入探讨如何利用强大的Java库Spire.Do... 目录1. Spire.Doc for Java 库介绍与安装特点与优势Maven 依赖配置2. 通过替换

Go语言实现桥接模式

《Go语言实现桥接模式》桥接模式是一种结构型设计模式,它将抽象部分与实现部分分离,使它们可以独立地变化,本文就来介绍一下了Go语言实现桥接模式,感兴趣的可以了解一下... 目录简介核心概念为什么使用桥接模式?应用场景案例分析步骤一:定义实现接口步骤二:创建具体实现类步骤三:定义抽象类步骤四:创建扩展抽象类步

C++中的解释器模式实例详解

《C++中的解释器模式实例详解》这篇文章总结了C++标准库中的算法分类,还介绍了sort和stable_sort的区别,以及remove和erase的结合使用,结合实例代码给大家介绍的非常详细,感兴趣... 目录1、非修改序列算法1.1 find 和 find_if1.2 count 和 count_if1

Redis中群集三种模式的实现

《Redis中群集三种模式的实现》Redis群集有三种模式,分别是主从同步/复制、哨兵模式、Cluster,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录1. Redis三种模式概述2、Redis 主从复制2.1 主从复制的作用2.2 主从复制流程2

深入理解MySQL流模式

《深入理解MySQL流模式》MySQL的Binlog流模式是一种实时读取二进制日志的技术,允许下游系统几乎无延迟地获取数据库变更事件,适用于需要极低延迟复制的场景,感兴趣的可以了解一下... 目录核心概念一句话总结1. 背景知识:什么是 Binlog?2. 传统方式 vs. 流模式传统文件方式 (非流式)流

Python实现Word文档自动化的操作大全(批量生成、模板填充与内容修改)

《Python实现Word文档自动化的操作大全(批量生成、模板填充与内容修改)》在职场中,Word文档是公认的好伙伴,但你有没有被它折磨过?批量生成合同、制作报告以及发放证书/通知等等,这些重复、低效... 目录重复性文档制作,手动填充模板,效率低下还易错1.python-docx入门:Word文档的“瑞士

使用Java填充Word模板的操作指南

《使用Java填充Word模板的操作指南》本文介绍了Java填充Word模板的实现方法,包括文本、列表和复选框的填充,首先通过Word域功能设置模板变量,然后使用poi-tl、aspose-words... 目录前言一、设置word模板普通字段列表字段复选框二、代码1. 引入POM2. 模板放入项目3.代码

Python进行word模板内容替换的实现示例

《Python进行word模板内容替换的实现示例》本文介绍了使用Python自动化处理Word模板文档的常用方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友... 目录技术背景与需求场景核心工具库介绍1.获取你的word模板内容2.正常文本内容的替换3.表格内容的

深度解析Python中递归下降解析器的原理与实现

《深度解析Python中递归下降解析器的原理与实现》在编译器设计、配置文件处理和数据转换领域,递归下降解析器是最常用且最直观的解析技术,本文将详细介绍递归下降解析器的原理与实现,感兴趣的小伙伴可以跟随... 目录引言:解析器的核心价值一、递归下降解析器基础1.1 核心概念解析1.2 基本架构二、简单算术表达

C#和Unity中的中介者模式使用方式

《C#和Unity中的中介者模式使用方式》中介者模式通过中介者封装对象交互,降低耦合度,集中控制逻辑,适用于复杂系统组件交互场景,C#中可用事件、委托或MediatR实现,提升可维护性与灵活性... 目录C#中的中介者模式详解一、中介者模式的基本概念1. 定义2. 组成要素3. 模式结构二、中介者模式的特点