在这篇文章里面,我介绍一下如何自己实现一个闭包,方便进行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>