一、std::enable_shared_from_this<T>
这是 CRTP 在标准库中最经典的应用。场景:你有一个 shared_ptr 管理的对象,对象内部需要生成指向自己的 shared_ptr。
class Widget : public std::enable_shared_from_this<Widget> {
public:
void register_callback() {
// 把一个回调注册到别处,回调要持有 Widget 的 shared_ptr
// 防止 Widget 被释放时回调还在执行
callback_mgr_.add([self = shared_from_this()] {
self->do_something();
});
}
};
没有 CRTP 会怎样?
如果 enable_shared_from_this 不是模板,它不知道派生类的类型,shared_from_this() 只能返回 shared_ptr<enable_shared_from_this>,不是 shared_ptr<Widget>。CRTP 让基类在编译期拿到派生类的类型,自然就能正确返回。
二、CRTP 实现实例计数
template <typename Derived>
class InstanceCounter {
static inline int count_ = 0;
protected:
InstanceCounter() { count_++; }
~InstanceCounter() { count_--; }
public:
static int instance_count() { return count_; }
};
class MyClass : public InstanceCounter<MyClass> {
// ...
};
class OtherClass : public InstanceCounter<OtherClass> {
// ...
};
// MyClass 和 OtherClass 有各自独立的 count_
MyClass a, b;
OtherClass c;
MyClass::instance_count(); // 2
OtherClass::instance_count(); // 1
因为 InstanceCounter<MyClass> 和 InstanceCounter<OtherClass> 是两个不同的类,它们的 static count_ 是独立的。