CRTP(Curiously Recurring Template)
,奇异递归模板
CRTP
是一种C++设计方法,类X派生自一个模板参数为Z的类模板Y,并且Y实例化为模板参数 Z=X
,如:
template <class Z>
class Y {};
class X : public Y<X> {};
1.简单例子
CRTP
可用于实现“编译时多态”,当基类暴露一个接口,派生类实现这样一个接口:
#include <iostream>
template<class Derived>
class Base {
public:
void name() {
static_cast<Derived*>(this)->Impl();
}
};
class D1 : public Base<D1> {
public:
static void Impl() {
std::cout << "D1::Impl()" << std::endl;
}
};
class D2 : public Base<D2> {
public:
static void Impl() {
std::cout << "D2::Impl()" << std::endl;
}
};
int main() {
D1 d1;
d1.name();
D2 d2;
d2.name();
return 0;
}
输出结果:
D1::Impl()
D2::Impl()
最核心的代码 static_cast<Derived*>(this)->Impl();
,这里就是将父类指针转换成子类指针,然后调用子类的实现方法。
2.不暴露实现
#include <iostream>
template<class Derived>
class Base {
public:
void name() {
static_cast<Derived*>(this)->Impl();
}
};
class D1 : public Base<D1> {
private:
friend Base<D1>;
static void Impl() {
std::cout << "D1::Impl()" << std::endl;
}
};
class D2 : public Base<D2> {
private:
friend Base<D2>;
static void Impl() {
std::cout << "D2::Impl()" << std::endl;
}
};
int main() {
D1 d1;
d1.name();
D2 d2;
d2.name();
return 0;
}
输出结果:
D1::Impl()
D2::Impl()
3.CRPT
好处
- (1) 静态多态:
CRTP
实现静态多态,无需使用虚函数,静态绑定,无运行时开销; - (2) 类型安全:
CRTP
提供了类型安全的多态性,通过模板参数传递具体子类类型,编译器能确保类型匹配,避免了传统向下转换可能引起的类型错误; - (3) 灵活接口设计:
CRTP
允许父类定义公共接口,并要求子类实现具体操作,这使得基类能提供通用接口,而具体实现细节留给派生类,其实也就是多态了。