用这个做关键词在google上搜索会得到一大堆文章,那些用c++实现的sig/slot库基本上都是以这个为基础,花了几个小时来检索,最后还是没有 找到合适的代码,我向来厌恶通用的完整的框架,觉得太复杂了,很难弄明白

例如ACE之类,网络程序框架从来都是自己手工写,代码里面充斥CSimpleSocket,CSimpleUDP,CSimpleSQL这样的名词,除了STL之外,几乎从不用模板,看着那些大而全的实现就发怵,不 得不自己从头造车轮

事情的起因是这样,我在程序里面需要实现一个函数链,研究了一下,有多种实现方法。

  • c的方案 定义一个函数指针,然后在声明一个指针数组,剩下的就是逻辑的实现了

  • c++的方案
    当然也可以延续c的做法,不过OOP的基本代码单元是类,要定义函数指针,带this指针的类成员函数是不行的了,哪只能定义一些静态成员函数,但这样的实现限制太多,何必披上c++的马甲呢。习惯的做法是声明一个接口,比如下面这个 struct IFoorbar { virtual void run()=0; };然后每个需要加入到函数链的宿主类都实现这个接口,cpp支持多重继承的好处就显现在这里.但是这样的做法也有弊端,就是每个类只能提供一个函数,如果想要在一个类里面提供多个函数,就得重新定义接口了,要加上一个功能标签。

struct IFoorbar
{
    virtual void run(int func_tag)=0;
};
    class Some:public IFoorbar
{
public:
virtual void run(int func_tag)
{
switch(func_tag):
{
case 1:
//do something 1
break;
case 2:
//do something 2
break;
}
}
};

这样做固然可行,但是太繁琐,而且在具体使用中,还有些小的缺陷,这就引出了委托。所谓委托,简而言之,就一个类成员变量的通用指 针的类型。在c#里,这个是自带的功能,Delphi也能够轻易的实现,因为它支持定义类成员函数的类型,这个也是Delphi仅有的几处在语法层面优于 c++的地方 type TCallBack = procedure of object;

委托的实现

struct ICallBack
{
    virtual void operator()()const =0;
    virtual ~ICallBack(){};
};

template
class Delegate:public ICallBack
{
typedef void (ObjectType::*FunctionPtr)(void);
public:
    Delegate(ObjectType * obj,FunctionPtr func):m_obj(obj),
    m_func(func)
    {
    }
    virtual void operator()() const
    {
        (m_obj->*m_func)();
    }

operator=(const Delegate & other)
{
    m_func = other.m_func;
    m_obj = other.m_obj;
}

private:
    FunctionPtr m_func;
    ObjectType * m_obj;
};
//-----------------------for test----------------------------
class A
{
public:
    void print()
    {
    printf("call me a\n");
    }
};

void run(const ICallBack *c)
{
    if(c)(*c)();
}

int _tmain(int argc, _TCHAR* argv[])
{
    A a;
    Delegate dg(&a,&A::print);
    run(&dg);
    return 0;
}

简单的说明

这个委托类是对应的是一个无参数和无返回值的类成员函数,可以根据实际情况做扩展 定义接口ICallBack的目的就是为了能够横向的切分代码,能够很简单的定义一个类型指针,而不需要加上template list,如果没有定义这个接口,那么上面的run函数就得定义如下 void run(const Delegate < A > &d) { ...... }

本文地址: http://lutaf.com/21.htm 鲁塔弗原创文章,欢迎转载,请附带原文链接