C#委托的C++实现

以前做开发时经常需要处理回调,但回调有时很不方便,所以那时实现了一个类似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__

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++ 并没有原生的委托机制,但可以通过函数指针和对象指针来模拟委托机制。 在 C++ 中,函数指针可以作为参数传递和返回值,可以使用函数指针来实现委托的功能。而对象指针可以用于保存对象的状态和数据,也可以用于调用对象的成员函数。 以下是一个简单的 C++ 示例代码,演示了如何通过函数指针和对象指针来实现委托机制: ```cpp #include <iostream> #include <functional> using namespace std; class Delegate { public: void (*func)(void*); // 函数指针 void* obj; // 对象指针 void Invoke() { func(obj); // 调用函数指针 } }; class Test { public: void Print() { cout << "Hello, world!" << endl; } }; void PrintTest(void* obj) { Test* test = (Test*)obj; // 将对象指针转换为 Test 类型指针 test->Print(); // 调用对象的成员函数 } int main() { Test test; Delegate delegate; delegate.func = PrintTest; delegate.obj = &test; delegate.Invoke(); // 调用委托 return 0; } ``` 在这个示例代码中,我们定义了一个 `Delegate` 类,其中包含了一个函数指针和一个对象指针。`Invoke` 函数用于调用委托。我们还定义了一个 `Test` 类,其中包含了一个成员函数 `Print`。在 `main` 函数中,我们创建了一个 `Test` 对象 `test`,并创建了一个 `Delegate` 对象 `delegate`,将 `PrintTest` 函数的地址和 `test` 对象的地址分别赋值给 `Delegate` 对象的函数指针和对象指针。最后,我们通过 `delegate.Invoke()` 调用委托,实际上就是调用了 `PrintTest` 函数,并将 `test` 对象传递给了该函数,从而调用了 `Test` 对象的 `Print` 成员函数。 需要注意的是,这只是一个简单的示例,实际的委托机制可能更加复杂,并且需要考虑线程安全等问题。如果需要使用委托机制,建议使用现有的 C++ 第三方库或框架,如 Boost、Qt 等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值