CRTP

CRTP

方式:父类是模板,然后定义一个子类继承它,并且模板参数是子类。

1
2
3
4
template<class Dervied>
class Base {};

class X : public Base<X> {};

CRTP作用

CRTP可用于在父类暴露接口,而子类实现该接口,以此实现”编译期多态(静态多态)”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template <class Dervied>
class Base {
public:
// 公开的接口函数 供外部调用
void addWater(){
// 调用子类的实现函数。要求子类必须实现名为 impl() 的函数
// 这个函数会被调用来执行具体的操作
static_cast<Dervied*>(this)->impl();
}
};

class X : public Base<X> {
// 声明友元类,使得父类可以访问到impl()函数
friend class Base<X>;
private:
// 子类实现了父类接口
void impl() const{
std::cout<< "X 设备加了 50 毫升水\n";
}
};

其中,static_cast<Dervied*>(this)将父类指针转化为子类指针而调用子类的方法。

这个转换是安全合法的。因为 this 指针实际上指向一个 X 类型的对象,X 类型对象继承了 Base<X> 的部分,X 对象也就包含了 Base<X> 的部分,所以这个转换在编译期是有效的,并且是合法的。

CRTP实现单例模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
template<class T>
class Singleton{
public:
static T& GetInstance(){
static T ins;
return ins;
}
protected:
Singleton() = default;
virtual ~Singleton(){};
Singleton(const Singleton<T> &) = delete;
Singleton<T>& operator=(const Singleton&) = delete
};

class A : public Singleton<A>{
friend class Singleton<A>;
private:
A(){};// 单例的构造函数必须是私有的
};

CRTP
http://example.com/2024/08/25/CRTP/
作者
haoks
发布于
2024年8月25日
许可协议