架构设计 - CRTP 奇异递归模板模式

作者:billy
版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处

一、什么是 CRTP?
CRTP(Curiously Recurring Template Pattern)直译是 “奇异递归模板模式”,核心特征是:一个类 A 继承自一个模板类,而这个模板类的模板参数正是类 A 本身。CRTP 在 C++ 标准库(如std::enable_shared_from_this)、开源框架(如 Boost)中广泛使用,是高性能 C++ 开发的重要技巧。

1. 最基础的 CRTP 结构

先看一个极简示例,直观理解结构:

// 模板类(基类) template <typename Derived> class Base { public: void do_something() { // 向下转型:将基类指针/引用转为派生类类型 Derived& derived = static_cast<Derived&>(*this); // 调用派生类的具体实现 derived.implementation(); } }; // 派生类:继承自Base<Derived>(模板参数是自己) class Derived : public Base<Derived> { public: void implementation() { std::cout << "Derived的具体实现" << std::endl; } }; // 测试代码 int main() { Derived d; d.do_something(); // 输出:Derived的具体实现 return 0; }
2. CRTP 的核心逻辑
  • 基类模板通过模板参数 “感知” 派生类的类型;
  • 基类中通过static_cast<Derived&>(*this)安全地将自身转为派生类对象;
  • 从而可以调用派生类的成员函数 / 成员变量,实现编译期的多态(区别于运行期的虚函数多态)。

二、CRTP 的核心用途(解决什么问题?)

CRTP 的核心价值是用编译期静态绑定替代运行期动态绑定,避免虚函数的开销,同时实现 “复用代码 + 定制化实现”

用途 1:静态多态(替代虚函数)

虚函数的多态是运行期确定调用哪个函数(有 vtable 开销),而 CRTP 在编译期就能确定,效率更高。

#include <iostream> using namespace std; // 基类模板:定义通用逻辑 template <typename Derived> class Shape { public: // 通用接口:计算面积 double area() const { // 调用派生类的具体计算逻辑 return static_cast<const Derived*>(this)->calc_area(); } }; // 圆形:定制calc_area class Circle : public Shape<Circle> { private: double radius; public: Circle(double r) : radius(r) {} // 派生类的具体实现 double calc_area() const { return 3.14159 * radius * radius; } }; // 矩形:定制calc_area class Rectangle : public Shape<Rectangle> { private: double width, height; public: Rectangle(double w, double h) : width(w), height(h) {} double calc_area() const { return width * height; } }; int main() { Circle c(2.0); Rectangle r(3.0, 4.0); // 统一接口调用,编译期确定调用哪个calc_area cout << "圆面积:" << c.area() << endl; // 输出:12.56636 cout << "矩形面积:" << r.area() << endl; // 输出:12 return 0; }
用途 2:实现 “混入(Mixin)” 功能

Mixin 是一种代码复用方式,CRTP 可以轻松实现 Mixin,给不同类批量添加通用功能(比如日志、计数、克隆)。

#include <iostream> #include <string> using namespace std; // Mixin:添加计数功能的CRTP基类 template <typename Derived> class Counter { private: static int count; // 静态变量:统计派生类对象数量 public: Counter() { count++; } ~Counter() { count--; } // 通用接口:获取当前对象数量 static int get_count() { return count; } }; // 静态变量初始化 template <typename Derived> int Counter<Derived>::count = 0; // 类A:混入计数功能 class A : public Counter<A> {}; // 类B:混入计数功能 class B : public Counter<B> {}; int main() { A a1, a2; B b1; cout << "A的对象数:" << A::get_count() << endl; // 输出:2 cout << "B的对象数:" << B::get_count() << endl; // 输出:1 { A a3; cout << "A的对象数:" << A::get_count() << endl; // 输出:3 } // a3析构 cout << "A的对象数:" << A::get_count() << endl; // 输出:2 return 0; }
用途 3:避免代码重复(静态多态的扩展)

比如实现 “可比较” 的类,CRTP 可以封装</>/==等比较逻辑,派生类只需实现核心的operator<:

template <typename Derived> class Comparable { public: // 封装通用比较逻辑 bool operator>(const Derived& other) const { return other < static_cast<const Derived&>(*this); } bool operator<=(const Derived& other) const { return !(static_cast<const Derived&>(*this) > other); } bool operator>=(const Derived& other) const { return !(static_cast<const Derived&>(*this) < other); } }; // 整数包装类:只需实现operator< class MyInt : public Comparable<MyInt> { private: int val; public: MyInt(int v) : val(v) {} // 核心比较逻辑 bool operator<(const MyInt& other) const { return val < other.val; } }; int main() { MyInt a(5), b(10); cout << (a > b) << endl; // 输出:0(false) cout << (a <= b) << endl; // 输出:1(true) return 0; }

三、CRTP 的关键注意事项

  1. 编译期确定类型:CRTP 的所有逻辑都在编译期完成,没有运行期开销,但也无法像虚函数那样 “动态绑定”(比如基类指针指向不同派生类对象);
  2. 转型安全性:必须确保模板参数是真正的派生类,否则 static_cast 会导致未定义行为;
  3. 与虚函数的区别:
    虚函数:运行期多态,灵活但有 vtable 开销;
    CRTP:编译期多态,高效但缺乏运行期灵活性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1165626.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Hunyuan MT1.8B翻译断句错误?格式保留功能启用教程

Hunyuan MT1.8B翻译断句错误&#xff1f;格式保留功能启用教程 1. 背景与问题引入 在多语言内容日益增长的今天&#xff0c;轻量级神经机器翻译&#xff08;NMT&#xff09;模型成为移动端和边缘设备的重要基础设施。HY-MT1.5-1.8B 是腾讯混元于 2025 年 12 月开源的轻量级多…

4个语音识别神器推荐:预置镜像开箱即用,5块钱全体验

4个语音识别神器推荐&#xff1a;预置镜像开箱即用&#xff0c;5块钱全体验 你是不是也遇到过这种情况&#xff1a;刚录完一段口播视频&#xff0c;准备剪辑时却发现还得一个字一个字手动打字幕&#xff1f;费时又费力&#xff0c;一不小心还容易出错。作为新媒体运营&#xf…

Stable Diffusion 3.5避坑指南:云端部署解决CUDA版本冲突

Stable Diffusion 3.5避坑指南&#xff1a;云端部署解决CUDA版本冲突 你是不是也经历过这样的崩溃时刻&#xff1f;兴冲冲地想在本地电脑上跑一跑最新的 Stable Diffusion 3.5&#xff08;SD3.5&#xff09;&#xff0c;结果刚打开命令行就报错&#xff1a;CUDA not available…

AI智能文档扫描仪参数详解:Canny边缘检测阈值设置建议

AI智能文档扫描仪参数详解&#xff1a;Canny边缘检测阈值设置建议 1. 引言 1.1 技术背景与应用场景 在数字化办公日益普及的今天&#xff0c;将纸质文档快速、清晰地转化为电子文件已成为高频需求。传统的扫描仪受限于设备体积和使用场景&#xff0c;而手机拍照虽便捷&#…

基于改进下垂控制的微电网控制研究(Simulink仿真实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

照片级AI绘画!Z-Image-Turbo生成写实图像体验

照片级AI绘画&#xff01;Z-Image-Turbo生成写实图像体验 1. 引言&#xff1a;从概念到高质量写实图像的飞跃 近年来&#xff0c;AI图像生成技术经历了从“抽象艺术”到“照片级真实感”的跨越式发展。阿里通义推出的 Z-Image-Turbo 模型&#xff0c;正是这一趋势下的代表性成…

【低压配电网】【对单相接地低压电网监测方案性能】在径向低压测试馈线上使用WLS状态估计器的性能,由于测量误差的随机性质,分析以蒙特卡洛方式进行(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

永磁同步电机PMSM六种DPWM调制技术-DPWM0 、DPWM1、DPWM2、DPWM3、DPWMMAX、DPWMMIN研究(Simulink仿真实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

ES6对象方法简写:更简洁的代码写法

ES6 中为对象字面量引入的「方法简写」语法&#xff0c;这是 ES6 简化对象写法的重要特性之一&#xff0c;能让对象方法的定义更简洁。方法简写的核心概念在 ES5 及更早版本中&#xff0c;定义对象方法需要明确写出 属性名: 函数 的形式&#xff1b;而 ES6 的方法简写则允许直接…

Z-Image-Turbo极速出图实战:6秒生成,成本低至1毛

Z-Image-Turbo极速出图实战&#xff1a;6秒生成&#xff0c;成本低至1毛 你是不是也经常为短视频封面发愁&#xff1f;每天要产出几十条内容&#xff0c;每一条都得配一张吸睛的封面图。以前靠手动设计&#xff0c;PS一顿操作猛如虎&#xff0c;结果一小时才出一张图&#xff…

TurboDiffusion为何快?SageSLA注意力机制深度解析

TurboDiffusion为何快&#xff1f;SageSLA注意力机制深度解析 1. 引言&#xff1a;视频生成加速的技术突破 近年来&#xff0c;文生视频&#xff08;Text-to-Video, T2V&#xff09;和图生视频&#xff08;Image-to-Video, I2V&#xff09;技术取得了显著进展。然而&#xff…

IndexTTS-2方言支持体验:云端快速测试,无需本地资源

IndexTTS-2方言支持体验&#xff1a;云端快速测试&#xff0c;无需本地资源 你是否正在参与一个方言保护项目&#xff0c;却苦于没有专业设备来测试AI语音合成效果&#xff1f;你是否希望快速验证某种方言的语音还原度&#xff0c;但又不想折腾复杂的本地部署和显卡配置&#…

ACE-Step模型优势剖析:3.5B参数如何平衡质量与速度

ACE-Step模型优势剖析&#xff1a;3.5B参数如何平衡质量与速度 1. 引言&#xff1a;音乐生成进入高效可控新时代 随着AIGC技术的快速发展&#xff0c;AI生成音乐正从“能出声”迈向“高质量、可控制、易使用”的新阶段。在这一趋势下&#xff0c;ACE-Step作为一款由ACE Studi…

NotaGen节日营销:快速生成品牌定制圣诞音乐的秘诀

NotaGen节日营销&#xff1a;快速生成品牌定制圣诞音乐的秘诀 你有没有遇到过这样的情况&#xff1f;年底将至&#xff0c;商场的节日氛围布置得热热闹闹&#xff0c;彩灯、雪人、麋鹿样样不落&#xff0c;可背景音乐却还是那几首翻来覆去的老歌——《Jingle Bells》《We Wish…

2026 年程序员接单全指南:平台这么多,别再选错了

这两年&#xff0c;行情慢慢冷静下来&#xff0c;岗位竞争也肉眼可见地卷了起来&#xff0c;身边不少程序员开始给自己留后路。有人想多赚点&#xff0c;给收入加个缓冲&#xff1b;有人想攒点真实项目&#xff0c;别简历一翻全是在职期间参与&#xff1b;也有人干脆把程序员接…

8GB内存电脑跑LoRA:云端GPU加持,性能提升10倍

8GB内存电脑跑LoRA&#xff1a;云端GPU加持&#xff0c;性能提升10倍 你是不是也有一台老旧笔记本&#xff0c;想尝试AI模型微调&#xff0c;却被“训练太慢”劝退&#xff1f;本地用LoRA训练一个epoch要8小时&#xff0c;风扇狂转、系统卡顿&#xff0c;结果还经常崩溃。别急…

Qwen3-Embedding-4B成本分摊:多团队使用计量部署教程

Qwen3-Embedding-4B成本分摊&#xff1a;多团队使用计量部署教程 1. 背景与挑战 随着大模型在企业内部的广泛应用&#xff0c;向量嵌入服务已成为搜索、推荐、知识管理等系统的核心基础设施。Qwen3-Embeding-4B作为通义千问系列中专为文本嵌入和排序任务设计的高性能模型&…

MiniMax 开源了一个新的 Coding Agent 评测集,叫 OctoCodingBench,用以去评测 Coding Agent 在完成任务的过程中,有没有遵守规矩?

OctoCodingBench&#xff1a;终于有人开始认真评测 Coding Agent “有没有守规矩”了 MiniMax 开源了一个新的 Coding Agent 评测集&#xff0c;叫 OctoCodingBench&#xff0c;用以去评测 Coding Agent 在完成任务的过程中&#xff0c;有没有遵守规矩&#xff1f; 我个人非常…

MiDaS开箱即用镜像:免去CUDA烦恼,5分钟部署

MiDaS开箱即用镜像&#xff1a;免去CUDA烦恼&#xff0c;5分钟部署 你是不是也遇到过这种情况&#xff1a;团队正在开发一款智能机器人&#xff0c;需要实现环境感知功能&#xff0c;比如判断前方障碍物有多远、地面是否平坦。这时候深度估计技术就派上用场了——而MiDaS正是目…

DeepSeek-OCR论文精读:用视觉压缩突破长文本处理瓶颈|基于DeepSeek-OCR-WEBUI实战

DeepSeek-OCR论文精读&#xff1a;用视觉压缩突破长文本处理瓶颈&#xff5c;基于DeepSeek-OCR-WEBUI实战 1. 写在前面&#xff1a;核心价值与技术定位 问题驱动&#xff1a;大语言模型&#xff08;LLM&#xff09;在处理超长文本时面临显存占用高、计算复杂度上升的瓶颈&…