CRTP是编译期静态多态技术,通过模板参数传递派生类类型实现零开销调用;传统继承是面向对象机制,可支持动态多态(需虚函数)或纯代码复用,二者本质不同。

CRTP 和普通继承根本不是同一类东西
CRTP(Curiously Recurring Template Pattern)是一种模板编程技巧,本质是**编译期的静态绑定**;而传统继承(比如 class Derived : public Base)是面向对象的基础机制,本身不决定多态方式——它既可支撑动态多态(配合虚函数),也可用于静态场景(无虚函数时只是代码复用)。很多人误以为“CRTP 是一种继承”,其实它只是**借用了公有继承的语法形式**,背后没运行时开销、不涉及虚表、也不支持向上转型为基类指针/引用(除非显式提供转换)。
静态多态:CRTP 是典型代表
静态多态指函数调用在**编译期就确定目标函数地址**,无需运行时查虚表。CRTP 通过模板参数把派生类类型传给基类,让基类能直接调用派生类的静态成员或函数:
- 基类是模板类:
templateclass Base { ... }; - 派生类继承时把自身传入:
class MyDerived : public Base{ ... }; - 基类中写
static_cast,编译器在实例化时就知道(this)->foo() foo是哪个具体类型里的函数 - 零运行时开销,支持内联,适合性能敏感场景(如数学库、嵌入式)
动态多态:靠虚函数 + 继承 + 多态指针/引用
动态多态依赖运行时机制:对象实际类型决定调用哪个函数版本。核心要素缺一不可:
- 基类声明虚函数(
virtual void func() = 0;) - 派生类重写该函数(
override) - 通过基类指针或引用调用:
Base* p = new Derived(); p->func(); - 每次调用需查虚函数表(vtable),有间接跳转开销(虽小但存在)
- 支持运行时类型识别(
dynamic_cast)、对象生命周期管理(多态析构需虚析构函数)
关键区别总结(直击本质)
发生时机:CRTP 在模板实例化时完成绑定;动态多态在运行时通过 vptr/vtable 解析。
类型安全:CRTP 编译期检查派生类是否提供所需接口(否则报错);动态多态只检查签名匹配,运行时才可能因未重写纯虚函数而崩溃(构造期间)。
灵活性:CRTP 要求派生类型在编译期已知,无法处理未知类型(如插件系统);动态多态可加载新 DLL 并创建派生类对象。
对象模型:CRTP 基类不包含虚表指针,对象更轻量;动态多态对象头部隐含 vptr,每个含虚函数的类都有 vtable。
立即学习“C++免费学习笔记(深入)”;











