c++模版的一些使用方法(四)

本文介绍适配器模式的应用实例,展示了如何利用模板适配器解决类型不匹配问题。此外,还探讨了函数封装的重要性及其实现方法,旨在提高代码的安全性和可维护性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

接着(三)的内容说,设计模式中有一种适配器模式,它的意思是,当两个接口不匹配时,创建一个适配器在中间进行转接,使原本不能在一起工作的两个接口可以在一起工作。这种类型不匹配的情况在普通代码层也会经常出现,比如函数的参数类型,模版的参数等。那么模版也可以起到适配器的作用。很好的例子是traits,stl中可以发到大量的使用。下面例子Responst类是一个模版类,接受一个参数T,要求T类型有一个func函数,以及A_type的类型定义,否则编不过。

template<class T>
class Responst
{
public:
    void show(T& t)
    {
        t->func();
    }
    typename T::A_type a;
};

class test
{
public:
    typedef double A_type;
    void func()
    {
    }
};

int main()
{
    Responst<test> r;
    //Responst<double> r1;//这行取消注释后编不过
}
那么如何让没有func函数和A_type类型定义的一个类型通过Responst模版?

可以用一个模版适配器。

定义一个模版类adapter来做为适配器,

template<class P>
class adapter
{
public:
    typedef typename P::A_type A_type;
    void func(P& t)
    {
        t->func();
    }
};

template<>
class adapter<double>
{
public:
    typedef int A_type;
    void func(int& t)
    {
    }
};
这样就可以使用Responst<double> r了。


XX的封装

XX代表函数,函数又分为全局函数或成员函数。

为什么要对函数进行封装呢?可以说有2个原因,而应用,则主要是在回调函数中。

一般的C类型回调函数会是这样的:

//定义回调函数类型

typedef void (*p)(int*);

//注册回调到A

A.register(p,(int*)para);//para表示p需要的参数

//使用完后反注册

A.unregister(p,(int*)para)


这样做有什么问题?

从功能上说,没问题。但是从安全的角度说,它是不安全的,注册时一起传入了指针参数para,那么它需要在A中使用,那么如果我在调用了A.register且还未调用A.unregister时,由于一些其他操作,破坏了指针para,那么A中回调p时因为使用了para指针,就有可能造成异常。

原因二,接口不友好,C类型的接口本身就是不友好的,并且站在面向对象的角度,我们应该使用对象进行注册,而不是将回调函数和其参数分开。


有了这样的需求,那么就可以通过函数的封装来实现,也就用到了模版。

可以设计一个模版类,用于将函数指针和其参数封装,在以后的某一个时间点通过这个模版类的对象去调用被封装的函数,该函数可以是全局函数,也可以是成员函数。

如下:

template<class T>
class function;
template<class R,class Pa,class C>
class function<R(C::*)(Pa)>//定义模版类,用于封装
{
public:
    typedef R(C::*fun)(Pa);
    function(fun ptr,C*p)
    {
        m_ptr = ptr;
        m_this = p; 
    }
    R operator()(Pa a)
    {
        return (m_this->*m_ptr)(a);
    }
private:
    fun m_ptr;
    C* m_this;
};

class B
{
public:
    int a(int b)
    {
        printf("%d\n",b);
        return 0;
    }
};

int main()
{
    B b;
    function<int(B::*)(int)> f(&B::a,&b);//封装
    f(100);//封装后可以任意键调用
}
关于回调,其实重点还不是在模版上,回调的安全性也不是靠上面的封装函数可以解决的,boost中有一套可以借鉴的方法来处理模版,而回调和事件,本身就是一个很大内容,以后有时间再研究。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值