您的位置:首页 > 其它

用模板和基类巧妙实现类方法的回调(消息映射的基本原理)

2011-03-22 17:48 441 查看
注:本文参考一位学长的博客。用模板和基类巧妙实现类方法的回调是在这位学长的指导下完成的。他的博文链接:

http://xuwenzhang.org/blog/category/c%e7%bc%96%e7%a8%8b%e6%8a%80%e6%9c%af/

主要的任务:

实现对象方法的回调。(静态函数或者全局函数的回调,这个很好实现,就不多说了)。这个技巧,常见于消息映射的实现。形象的说,A对象有一个方法show(),但是B在没有A对象指针的前提下,如何调用A的show()方法。

难点:

对象方法指针的获取。

不多说了,直接上代码。

//辅助类:基类
class CallBack_Base
{
public:
//重载()操作符 即函数调用操作符
virtual void operator()()=0;
/**
巧妙点一:用虚拟函数,实现回调函数的调用
*/
};

//辅助类:用模版来传递类型
template <class Instance,class FunType>
class CallBack_0:public CallBack_Base
{
private:
FunType func;//对象的方法
Instance* ins;//对象的指针
public:
//在构造函数里面保存对象的指针和对象的方法
CallBack_0(Instance* ins,FunType func)
{
this->func = func;
this->ins = ins;
}
~CallBack_0(){};

//实现函数调用
void operator ()()
{
(ins->*func)();
}
};

//管理类
class CallBack
{
CallBack_Base* callback[100];
public:

template <class Instance,class FunType>
void reg(int id,Instance* ins,FunType func)//注册回调函数
{
callback[id] = new CallBack_0<Instance,FunType>(ins,func);
}
/**
巧妙点二:在调用模板方法的时候,编译器会自动帮填充模版,
即调用reg函数的时候可以不用传递Instance和FunType这两个类型(见main函数)
*/

//激活回调函数
void callBack(int id)
{
(*callback[id])();
}
};

//测试类
class Test
{
int a;
public:
void show()
{
printf("Test:hello!/n");
}
void set()
{
a = 10;
}
void get()
{
printf("a=%d/n",a);
}
};

int main(int argc, char* argv[])
{
CallBack callback;
Test     test;

//注册回调函数 test.show()
callback.reg(0,&test,&Test::show);
callback.callBack(0);//调用回调函数

/************************************************************************/
/* 对于使用者来说,根本意识不到模版的存在。                             */
/*这就是用模板和虚拟函数配合实现的巧妙之处                              */
/************************************************************************/

callback.reg(0,&test,&Test::set);
callback.reg(1,&test,&Test::get);

callback.callBack(0);
callback.callBack(1);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: