奇异递归模板(CRTP)
通过将基类模板参数设置为子类,从而实现静态多态(静态接口)、或者扩展接口(委托实现)
案例1
template <typename T>
class Base
{
public:
void process_imp()
{
cout << "base::process()" << endl;
}
//将基类指针转型为子类T类型的指针
T* sub()
{
return static_cast<T*>(this);
}
void process()
{
sub()->process_imp();//编译时多态
}
~Base()
{
cout << "~Base()" << endl;
}
void destroy()
{
delete static_cast<T*>(this);//多态析构
}
};
class Sub1 : public Base<Sub1>
{
public:
void process_imp()
{
cout << "Sub1::process_imp()" << endl;
}
~Sub1()
{
cout << "~Sub1" << endl;
}
};
class Sub2 : public Base<Sub2>
{
public:
void process_imp()
{
cout << "Sub2::process_imp()" << endl;
}
~Sub2()
{
cout << "~Sub2" << endl;
}
};
template <typename T>
void invoke(Base<T>* pb)
{
pb->destroy();
}
int main()
{
{
Base<Sub1>* ps1 = new Sub1();
ps1->process();
invoke(ps1);
//ps1->destroy();//作用同invoke(ps1)一致
Base<Sub2>* ps2 = new Sub2();
ps2->process();
invoke(ps2);
//ps2->destroy();
//ps2->~Base(); //只析构基类的对象,子类对象没有析构
}
getchar();
return 0;
}
- class Sub1:public Base< Sub1>,通过参数将子类类型在编译器时注入基类,从而实现在基类中提前获取子类类型信息;
- static_cast<T*>(this)将基类指针类型转化为子类T的指针
- Base类型为不完全类型,不能使用Sub1参与内存布局,但是可以再函数调用时使用(发生调用,模板编译时辨析即可)
- 删除对象,也要使用编译时多态进行删除
案例二:
模板实现多态深克隆
//接口类
class Shape {
public:
virtual ~Shape() = default;
virtual void process() = 0;
virtual unique_ptr<Shape> clone() const = 0;
};
template <typename T>
class CloneShape : public Shape
{
public:
unique_ptr<Shape> clone() const override
{
return make_unique<T>(static_cast<T const&>(*this));
}
};
class Rectangle : public CloneShape<Rectangle> {
public:
Rectangle() {}
Rectangle(const Rectangle& rhs)
{
cout << "Rectangle deep clone" << endl;
}
void process() override {
cout << "Rectangle process" << endl;
}
};
class Circle : public CloneShape<Circle> {
public:
Circle() {}
Circle(const Circle& rhs)
{
cout << "Circle deep clone" << endl;
}
void process() override
{
cout << "Circle process" << endl;
}
};
void invoke(const Shape& shape)
{
unique_ptr<Shape> ps = shape.clone();
ps->process();
}
int main()
{
Rectangle r;
invoke(r);
Circle c;
invoke(c);
vector<bool> vv;
getchar();
return 0;
}
案例三
enable_shared_from_this简单实现
template<typename T>
class enable_shared_from_this
{
private:
weak_ptr<T> weak_this;
protected:
constexpr enable_shared_from_this() noexcept { }
enable_shared_from_this(const enable_shared_from_this&) noexcept { }
enable_shared_from_this& operator=(const enable_shared_from_this&) noexcept
{
return *this;
}
~enable_shared_from_this() { }
public:
shared_ptr<T> shared_from_this() //获取一个子类的共享指针
{
return shared_ptr<T>(this->weak_this);
}
shared_ptr<const T> shared_from_this() const
{
return shared_ptr<const T>(this->weak_this);
}
};
// 扩展接口: 父类里面注入子类信息
class Widget : public std::enable_shared_from_this<Widget> {
public:
std::shared_ptr<Widget> getWidget()
{
//返回对象的this指针时,需要使用shared_from_this()
return shared_from_this();
}
void invoke()
{
process(shared_from_this());
}
void print()
{
cout<<"print"<<endl;
}
~Widget()
{
cout<<"~Widget()"<<endl;
}
//工厂函数创建对象,避免两个以上的智能指针指向一个裸指针
static std::shared_ptr<Widget> create()
{
return std::shared_ptr<Widget>(new Widget());
}
private:
Widget()=default;
};