c++ 常见模式之CRTP
CRTP(Curiously Recurring Template Pattern,奇异递归模板模式)是 C++ 中一种常见的静态多态实现技术,也是很多高性能库(如 Eigen、Boost、LLVM)中的核心设计模式之一。
💡 CRTP 本质定义
CRTP 是一种用子类作为模板参数传递给父类的技术。
📌 基本语法:
template <typename Derived>
class Base {
public:
void interface() {
// 调用派生类实现的方法
static_cast<Derived*>(this)->implementation();
}
// 可选默认实现
void implementation() {
std::cout << "Base implementation\n";
}
};
class Derived : public Base<Derived> {
public:
void implementation() {
std::cout << "Derived implementation\n";
}
};
调用方式:
int main() {
Derived d;
d.interface(); // 输出:Derived implementation
}
✅ CRTP 的主要用途
1. 实现静态多态(Static Polymorphism)
- 替代虚函数机制,避免运行时开销(如 vtable、动态绑定等)。
2. 代码复用
- 基类可以定义通用接口逻辑,细节延迟到派生类实现。
3. 在编译期做优化
- 比如 Eigen 库使用 CRTP 编写矩阵类,实现表达式模板,从而避免中间对象、提升性能。
🧠 CRTP 与虚函数的对比
特性 | 虚函数(动态多态) | CRTP(静态多态) |
---|---|---|
多态绑定 | 运行时 | 编译期 |
开销 | 有虚表开销 | 零开销 |
灵活性 | 更高 | 限制派生结构 |
可扩展性 | 高 | 较低 |
使用场景 | 插件式架构、通用接口 | 高性能场景、模板库 |
📦 典型应用案例
1. 编写通用操作接口
template <typename Derived>
class Shape {
public:
void draw() {
static_cast<Derived*>(this)->drawImpl();
}
};
class Circle : public Shape<Circle> {
public:
void drawImpl() {
std::cout << "Drawing Circle\n";
}
};
class Square : public Shape<Square> {
public:
void drawImpl() {
std::cout << "Drawing Square\n";
}
};
2. 实现计数器(统计子类个数)
template <typename T>
class Counter {
public:
Counter() { ++count; }
static int count;
};
template <typename T>
int Counter<T>::count = 0;
class MyClassA : public Counter<MyClassA> {};
class MyClassB : public Counter<MyClassB> {};
🔍 高级话题
● 与策略模式结合
template <typename Derived>
class Sorter {
public:
void sort() {
static_cast<Derived*>(this)->doSort();
}
};
class QuickSorter : public Sorter<QuickSorter> {
public:
void doSort() {
std::cout << "Quick Sort\n";
}
};
● 表达式模板(如 Eigen)
Eigen 用 CRTP 实现表达式模板,以支持像 C = A + B
这样的操作不会生成临时变量,而是按需展开计算。
🧩 总结
项目 | 说明 |
---|---|
类型 | 模板设计模式 |
优势 | 静态多态、零开销 |
缺点 | 结构固定、调试复杂 |
典型使用 | Eigen、Boost、LLVM |
ps:Eigen 是一个 高性能 C++ 线性代数库,广泛用于矩阵运算、向量计算、数值解法等领域。许多著名的框架都使用它作为矩阵运算库。例如TensorFlow,OpenCV等。