以前做开发时经常需要处理回调,但回调有时很不方便,所以那时实现了一个类似C#委托的东东。
这个东东一般可以使用回调替代,但有一种情况不好替代,类成员回调的声明往往类型未知,
这就是我要写这个东东的最主要动机。后来针对参数定制不灵活还有完善,但其实现没有个这简洁,
所以只发表这个最简洁的版本喽,吼吼!
如果哪位想传载本文,悉听尊便,如果能保留本文出处饿会很感谢.
http://kenny-office.blog.163.com/blog/static/307869272010010028561/
2010-7-19 02:29 严重厚道
// 文件名称: entrust.h
// 文件描述: 定义委托模板,使C++可以支持类似C#的委托语法.
// 文件作者: kenny
// 创建时间: 2006-8-8 16:36
// 修改记录:
// * 2006-10-12 11:46 修改不恰当的注释
// * 2006-10-12 11:49 去除对委托调用的异常捕获, 使用户可以自定义.
// * 2008-3-31 10:46:20 修改名字空间命名,const修饰及添加clear方法
// * 2008-5-23 11:24:00 重新设计了类型安全版的委托tentrust2
// * 2009-3-16 11:24:00 添加演示程序
//演示程序:
//
//#include <sstream>
//
//using namespace std;
//
//class TTest
//{
//public:
// bool CALL_ENTRUST test_m(int, bool) { return true; }
//};
//
//int CALL_ENTRUST test_g(const char* s, double& n) {
// istringstream iss(s);
// iss >> n;
// return 0;
//}
//
//typedef nsKLIB::tentrust<int, bool, bool> TEntrust1;
//typedef nsKLIB::tentrust<const char*, double&, int> TEntrust2;
//
//void demo()
//{
// TTest test;
// TEntrust1 e1(&test, &TTest::test_m);
// TEntrust2 e2(&test_g);
//
// bool ret1 = e1(3, true); //相当与调用了test.test_m(), 实际使用时e1可以保存或传递到任何有效周期内的代码中调用.支持动态链接库.
//
// double outret = double();
// int ret2 = e2("35.023", outret); //相当于调用了test_g(), 实际使用时e1可以保存或传递到任何有效周期内的代码中调用.支持动态链接库.
//
//}
//
#if !defined(__ENTRUST_H_2006_8_8_KENNY__)
#define __ENTRUST_H_2006_8_8_KENNY__
namespace nsKLIB
{
#if defined(__WINVER__) || defined(_MSC_VER) || defined(__BORLANDC__)
//如果是WINCE或是WIN32平台需要指定一下参数栈操作方式
#define CALL_ENTRUST __stdcall
#else
#define CALL_ENTRUST
#endif
namespace nsIMP
{
// 这个接口可以透明类成员委托和全局成员或静态成员委托间的差异
template<typename _type_in,
typename _type_out,
typename _type_ret>
struct tcaller {
//调用处理例程
virtual _type_ret call_function(_type_in __in, _type_out __out) = 0;
//给出委托的复本
virtual tcaller<_type_in, _type_out, _type_ret>* get_copy() = 0;
//释放委托对象
virtual void release() = 0;
};
// 类成员调用接口相关实现
template<typename _type_object,
typename _type_in,
typename _type_out,
typename _type_ret>
struct tcaller_member_ref :
public tcaller<_type_in, _type_out, _type_ret>
{
tcaller_member_ref(_type_object* obj, _type_ret (CALL_ENTRUST _type_object::* func)(_type_in, _type_out))
: __object(obj), __func(func) {}
virtual _type_ret call_function(_type_in arg_in, _type_out arg_out) {
return (__func)? ((__object->*__func)(arg_in, arg_out)) : _type_ret();
}
virtual tcaller<_type_in, _type_out, _type_ret>* get_copy() {
return new tcaller_member_ref<
_type_object, _type_in, _type_out, _type_ret>(__object, __func);
}
virtual void release() { delete this; }
_type_object* __object;
_type_ret (CALL_ENTRUST _type_object::*__func)(_type_in, _type_out);
};
// 全局或静态成员接口相关实现
template<typename _type_func,
typename _type_in,
typename _type_out,
typename _type_ret>
struct tcaller_global_ref : public tcaller<_type_in, _type_out, _type_ret> {
tcaller_global_ref(_type_func func) : __func(func) {}
virtual _type_ret call_function(_type_in arg_in, _type_out arg_out) {
return ((__func)? __func(arg_in, arg_out) : _type_ret());
}
virtual tcaller<_type_in, _type_out, _type_ret>* get_copy() {
return new tcaller_global_ref<
_type_func, _type_in, _type_out, _type_ret>(__func);
}
virtual void release() { delete this; }
_type_func __func;
};
// 委托实现模板
template<typename _type_in, //输入参数类型,用户可以自定义类型,其用途不限定为输入参数
typename _type_out = void*, //输出参数类型,用户可以自定义类型,其用途不限定为输出参数
typename _type_ret = int> //委托返回类型,用户可以自定义类型
class tentrust2
{
public:
typedef _type_in tin;
typedef _type_out tout;
typedef _type_ret tret;
typedef tentrust2<tin, tout, tret> tthis;
public:
tentrust2() : __call_ptr(0) {}
//----------------------------------------------------------------------------------------//
//通过类实例和类成员构造一个委托
// 参数:
// object 程序入口的类实例
// func 程序入口的类成员偏移
template<typename _type_object>
explicit tentrust2(_type_object* object,
tret (CALL_ENTRUST _type_object::*func)(tin, tout))
: __call_ptr(new tcaller_member_ref<_type_object, tin, tout, tret>(object, func)) {}
//----------------------------------------------------------------------------------------//
//通过全局成员或静态成员构造一个委托
// 参数:
// func 全局成员或静态成员地址
explicit tentrust2(tret(CALL_ENTRUST *func)(tin, tout))
: __call_ptr(new tcaller_global_ref<tret(CALL_ENTRUST*)(tin, tout), tin, tout, tret>(func)) {}
//----------------------------------------------------------------------------------------//
//这个就不多说了,拷贝构造函数
tentrust2(const tentrust2<tin, tout, tret>& ins) : __call_ptr(
(ins.__call_ptr) ? (ins.__call_ptr->get_copy()) : 0) {
__call_ptr = (ins.__call_ptr) ? (ins.__call_ptr->get_copy()) : 0;
}
//----------------------------------------------------------------------------------------//
//通过类实例和类成员使委托绑定到一个处理例程
// 参数:
// object 处理例程的类实例
// func 处理例程的类成员偏移
template<typename _type_object>
bool plug(_type_object* object,
tret(CALL_ENTRUST _type_object::*func)(tin, tout)) {
this->clear();
__call_ptr = new tcaller_member_ref<_type_object, tin, tout, tret>(object, func);
return 0 != __call_ptr;
}
//----------------------------------------------------------------------------------------//
//通过全局成员或静态成员使委托绑定到一个处理例程
// 参数:
// func 全局成员或静态成员的函数地址
bool plug(tret(CALL_ENTRUST *func)(tin, tout)) {
this->clear();
__call_ptr = new tcaller_global_ref<
tret(CALL_ENTRUST*)(tin, tout), tin, tout, tret>(func);
return 0 != __call_ptr;
}
//----------------------------------------------------------------------------------------//
//这个也不多说了,拷贝操作符
template<typename _type_in2, //输入参数类型
typename _type_out2, //输出参数类型
typename _type_ret2> //委托返回类型
tthis& operator=(tentrust2<_type_in2, _type_out2, _type_ret2>& ins) {
if( this != &ins ) {
this->clear();
__call_ptr = ((ins.__call_ptr)? ins.__call_ptr->get_copy() : 0);
}
return *this;
}
//----------------------------------------------------------------------------------------//
~tentrust2() { this->clear(); }
//----------------------------------------------------------------------------------------//
//调用委托绑定的例程,就像调用例程本身一样
tret operator()(tin arg_in, tout arg_out) {
return (__call_ptr)? __call_ptr->call_function(arg_in, arg_out) : tret(); }
//----------------------------------------------------------------------------------------//
//调用委托绑定的例程,就像调用例程本身一样
tret operator()(tin arg_in) {
return (__call_ptr)? __call_ptr->call_function(arg_in, tout()) : tret(); }
//----------------------------------------------------------------------------------------//
//清除委托到例程的绑定
void clear() {
if( __call_ptr ) {
tcaller<tin, tout, tret>* tmp = __call_ptr;
__call_ptr = 0;
tmp->release();
}
}
//----------------------------------------------------------------------------------------//
//判断委托是否已经绑定到某一例程
bool empty() const { return 0 == __call_ptr; }
operator bool() const { return !empty(); }
private:
tcaller<tin, tout, tret>* __call_ptr;
};
}
using namespace nsIMP;
#define tentrust tentrust2
template<typename _type_object,
typename _type_in,
typename _type_out,
typename _type_ret>
tentrust<_type_in, _type_out, _type_ret>
entrust_create(_type_object* o,
_type_ret (CALL_ENTRUST _type_object::*f)(_type_in, _type_out)) {
return tentrust<_type_in, _type_out, _type_ret>(o, f);
}
} //namespace nsKLIB
#endif //__ENTRUST_H_2006_8_8_KENNY__