关于c++委托机制的实现(二)

5 篇文章 0 订阅
4 篇文章 0 订阅

写自己的bug,让自己无bug可写

上一篇博客地址:https://blog.csdn.net/qq_34236354/article/details/89876304,有兴趣的可以去看看

下一篇博客地址:https://blog.csdn.net/qq_34236354/article/details/89881722,有兴趣的可以去看看

函数简介:c++中有普通函数,类静态成员函数,类普通成员函数,lamda函数

普通函数:一般指全局函数

类静态成员函数:类的静态函数,可以通过Class::Fun()形式调用

类普通成员函数:类的普通成员函数,一般是obj.fun()或pObj->fun()形式调用

lamda函数:有兴趣的可以自己百度,这里不考虑;(因为lamda函数实质是匿名函数,就是一个没有函数名的函数,从它的用途上来说本来就是提供编码便利,并且其他地方并不会出现,如果有两个或两个以上地方需要调用,那最好还是换成普通函数)

一:本次实现的是任意返回类型,任意类型形参函数的委托 (这里的函数必须有且只有一个形参,下一次讲任意数量形参的情况)

二:实现

    因为根本不知道客户端在使用时会用什么类型的返回值,有什么类型的形参,所以这里就需要使用到模板,在之前的抽象类基础上,稍加修改即可,代码如下

template <typename TReturn, typename TParam>
class IFun
{
public:
    virtual ~IFun() {}
    
    virtual TReturn operator()(TParam) = 0;
};

    关于普通函数和类的静态成员函数,为了适应任何类型返回值, 任意类型参数,也需要使用模板,并继承IFun抽象类,代码如下

template <typename TReturn, typename TParam>
class CStaticFun : public IFun<TReturn, TParam>
{
    typedef TReturn(*PFun)(TParam);
public:
    explicit CStaticFun(PFun pFun) : m_pFun(pFun) {}
    
    virtual TReturn operator()(TParam param) override
    {
        return m_pFun(param);
    }
private:
    PFun m_pFun;
};

    同理关于类的成员函数也要用模板,代码如下

template <typename TObj, typename TReturn, typename TParam>
class CMemberFun : public IFun<TReturn, TParam>
{
    typedef TReturn(TObj::*PFun)(TParam);
public:
    explicit CMemberFun(TObj *pObj, PFun pFun) : m_pObj(pObj), m_pFun(pFun) {}
    
    virtual TReturn operator()(TParam param) override
    {
        return (m_pObj->*m_pFun)(param);
    }
private:
    TObj *m_pObj;
    PFun  m_pFun;
};

    为了提供给客户端良好的接口,因此再创建一个类类统一接口

template <typename TReturn, typename TParam>
class CFun : public IFun<TReturn, TParam>
{
public:
    explicit CFun(TReturn(*pFun)(TParam)) : m_pFun(new CStaticFun<TReturn, TParam>(pFun)) {}
    ~CFun() { delete m_pFun; }
    
    template <typename TObj>
    explicit CFun(TObj *pObj, TReturn(TObj::*pFun)(TParam)) : m_pFun(new CMemberFun<TObj, TReturn, TParam>(pObj, pFun)) {}
    
    virtual TReturn operator()(TParam param) override
    {
        assert(m_pFun);
        return (*m_pFun)(param);
    }
private:
    IFun<TReturn, TParam> *m_pFun;
};

这样任意类型返回值任意类型形参函数的委托基本上就完成了

下面是实例:

#include <iostream>
#include <cassert>
#include <string>
 
/*
 * 把上面三个类的代码复制粘贴到这里
 */

bool fun(int i) { std::cout << "这是一个函数 i = " << i << std::endl; return false; }
class A
{
public:
    explicit A() {}
    static void fun1() { std::cout << "这是类的静态函数" << std::endl; }
    void fun2(char c) { std::cout << "这是类的成员函数 c = " << c << std::endl; }
};

int main()
{
    A a;
    CFun<bool, int> f(fun);
    //CFun<void, void> f1(&A::fun1); 因为这里必须要有一个参数,所以如果加入这一句编译不过,但返回值无所谓
    CFun<void, char> f2(&a, &A::fun2);
    
    CFun<int, double> lamda([](double a) -> int {
        std::cout << "lamda a = " << a << std::endl;
        return 0;
    });
    
    f(233333);
    //f1();
    f2('A');
    lamda(3.1415);
    
    return 0;
}

运行结果如下:

这是一个函数 i = 233333

这是类的成员函数 c = A  

lamda a = 3.1415

下一次 将在这基础上实现任意返回类型任意数量任意类型形参的函数的委托(其实只需要利用到c++中的可变参数就可以做到这一点)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值