奇异递归模板(CRTP)

奇异递归模板(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;
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值