C++分析研究  
C++
日历
<2013年10月>
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789
统计
  • 随笔 - 92
  • 文章 - 4
  • 评论 - 4
  • 引用 - 0

导航

常用链接

留言簿

随笔档案

文章档案

搜索

  •  

最新评论

阅读排行榜

评论排行榜

 
  在这篇文章里面,我介绍一下如何自己实现一个闭包,方便进行C++的类函数回调。该闭包能够接受任意类以及类成员做参数。
 
   * 闭包概念
 
   来源于大名鼎鼎的wikipedia:
 
   In computer science, a closure is a function that is evaluated in an
 
   environment containing one or more bound variables. When called, the function can access these variables.
 
   就是说闭包绑定了一个函数以及该函数调用发生需要的所有参数。当闭包被调用的时候,相当于函数被调用,而且可以访问绑定的参数托福答案
 
   * 第一步,能接受任意类型的类对象
 
   这是第一个实现
 
   <code>
 
   template<typename T>
 
   class Closure {
 
   typedef void (T::Func)();
 
   public:
 
   Closure(T* obj, Func f):
 
   obj_(obj), f_(f) {
 
   }
 
   void Run() {
 
   (obj_::*f_)();
 
   }
 
   private:
 
   T *obj_;
 
   Func *f_;
 
   };
 
   </code>
 
   使用起来
 
   <code>
 
   class MyClass {
 
   public:
 
   void PrintName() { cout 《 "MyClass"; }
 
   };
 
   MyClass obj;
 
   Closure<MyClass> closure(obj, &MyClass::PrintName);
 
   closure.Run();
 
   </code>
 
   看起来不错,是吧:-)
 
   但是还不能绑定参数呢我们来解决这个问题,让他能绑定一个参数先。
 
   * 第二步,能绑定一个任意类型参数
 
   <code>
 
   template<typename T, typename Arg>
 
   class Closure {
 
   typedef void (T::Func)(Arg);
 
   public:
 
   Closure(T* obj, Func f, Arg a):
 
   obj_(obj), f_(f), a_(a) {
 
   }
 
   void Run() {
 
   (obj_::*f_)(a_);
 
   }
 
   private:
 
   T *obj_;
 
   Func *f_;
 
   Arg a_;
 
   };
 
   </code>
 
   使用方法
 
   <code>
 
   class MyClass {
 
   public:
 
   void PrintName(const string& name) { cout 《 name; }
 
   };
 
   MyClass obj;
 
   Closure<MyClass, string> closure(obj, &MyClass::PrintName, "MyName");
 
   closure.Run();
 
   </code>
 
   哈哈,很好!现在可以绑定参数罗~~
 
   那怎么可以绑定两个参数呢?嘿嘿,自己想吧~
 
   现在这个使用方法我觉得很难看,既然调用方法都是统一的void
 
   Run(),我们应该可以让它使用起来更简单。 而且如果我要把两个不同的
 
   closure传给某个函数就做不到。
 
   比如:
 
   <code>
 
   class MyClass {
 
   public:
 
   void PrintName(const string& name) { cout 《 name; }
 
   };
 
   class MyClass_2 {
 
   public:
 
   void PrintValue(int val) { cout 《 val; }
 
   }
 
   // 这个函数怎么写才能让两个不同的closure都可以传进来?
 
   void func(???* closure) { closure->Run(); }
 
   MyClass obj;
 
   Closure<MyClass, string> closure1(obj, &MyClass::PrintName, "MyName");
 
   MyClass_2 obj2;
 
   Closure<MyClass_2, int> closure2(obj, &MyClass::PrintValue, 11);
 
   closure.Run();
 
   </code>
 
   * 第三步,使用起来更简单的Closure
 
   <code>
 
   // 基类;
 
   class Closure {
 
   public:
 
   virtual void Run() = 0;
 
   };
 
   // 实现支持一个参数的Closure;
 
   template<typename T, typename Arg>
 
   class OneArgClosure: public Closure {
 
   typedef void (T::Func)(Arg);
 
   public:
 
   Closure(T* obj, Func f, Arg a):
 
   obj_(obj), f_(f), a_(a) {
 
   }
 
   virtual void Run() {
 
   (obj_::*f_)(a_);
 
   }
 
   private:
 
   T *obj_;
 
   Func *f_;
 
   Arg a_;
 
   };
 
   // 辅助函数
 
   Template<typename T, typename Arg>
 
   Closure* NewClosure((T* obj, Func f, Arg a) {
 
   return OneArgClosure(obj, f, a);
 
   }
 
   </code>
 
   使用起来简单多啦
 
   <code>
 
   class MyClass {
 
   public:
 
   void PrintName(const string& name) { cout 《 name; }
 
   };
 
   MyClass obj;
 
   Closure* closure = NewClosure(obj, &MyClass::PrintName, "MyName");
 
   closure->Run();
 
   delete closure;
 
   </code>
 
 
posted on 2013-10-22 15:19 HAOSOLA 阅读(1118) 评论(1)  编辑 收藏 引用
评论:
  • # re: C++中的通用Closure   crabshai Posted @ 2013-10-23 00:15
    不就是std::function么?再加上std::bind或者lambda已经顶天了  回复  更多评论   


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理


 
Copyright © HAOSOLA Powered by: 博客园 模板提供:沪江博客
PK10开奖 PK10开奖