上一篇介绍了函数指针的基本用法,本篇看一下函数指针的应用。很多时候遇到的都是C函数的callback,下面示例展示C++中使用callback。
模板类,该类拥有2个成员,一个是对象指针,一个是成员函数,成员函数必须无参,无返回值。
struct CallbackAction { virtual void Execute() = 0; virtual ~CallbackAction() {} }; template <class OBJECT, class METHOD> struct CallbackMethodAction : public CallbackAction { OBJECT *object; METHOD method; void Execute() { (object->*method)(); } CallbackMethodAction(OBJECT *object, METHOD method) : object(object), method(method) {} };
class Callback{ public: explicit Callback(CallbackAction *newaction) { action = newaction; } Callback() { action = NULL; } ~Callback(); Callback(const Callback& c); Callback& operator=(const Callback& c); void Execute() const { if(action) action->Execute(); } void operator()() const { Execute(); } private: CallbackAction *action; }; Callback::Callback(const Callback& c) { action = c.action; } Callback::~Callback() { } Callback& Callback::operator=(const Callback& c) { action = c.action; return *this; }
template <class OBJECT, class METHOD> Callback callback(OBJECT *object, void (METHOD::*method)()) { return Callback(new CallbackMethodAction<OBJECT, void (METHOD::*)()>(object, method)); }
看一下如何应用
class Girl { public: void Shopping() { cout << "I want to shopping" << endl; WhenShopping(); } Callback WhenShopping; }; class Boy { public: void Bind(Girl* girl) { girl->WhenShopping = callback(this, &Boy::OnShopping); } private: void OnShopping() {cout << "I know she is shopping" << endl;} };
void main() { Girl girl; Boy boy; boy.Bind(&girl); girl.Shopping(); }
输出结果:
I want to shopping
I know she is shopping上面的的代码只是个callback使用的雏形,没有处理内存问题和由const修饰的参数问题,直接使用会有内存泄露。另外,如果需要带参数的函数指针类型,需要再扩展。
下面是带1个参数和带2个参数的函数指针类型的应用,更多参数的函数指针这里就不再展示了。
template <class P1> struct Callback1Action { virtual void Execute(P1 p1) = 0; virtual ~Callback1Action() {} }; template <class OBJECT, class METHOD, class P1> struct Callback1MethodAction : public Callback1Action<P1> { OBJECT *object; METHOD method; void Execute(P1 p1) { (object->*method)(p1); } Callback1MethodAction(OBJECT *object, METHOD method) : object(object), method(method) {} }; template <class P1> class Callback1{ public: explicit Callback1(Callback1Action <P1> *newaction) { action = newaction; } Callback1() { action = NULL; } ~Callback1(); Callback1& operator=(const Callback1& c); Callback1(const Callback1& c); void Execute(P1 p1) const { if(action) action->Execute(p1); } void operator()(P1 p1) const { Execute(p1); } private: Callback1Action<P1> *action; }; template <class P1> Callback1<P1>& Callback1<P1>::operator=(const Callback1& c) { action = c.action; return *this; } template <class P1> Callback1<P1>::Callback1(const Callback1& c) { action = c.action; } template <class P1> Callback1<P1>::~Callback1() { } // 接口函数 template <class OBJECT, class METHOD, class P1> Callback1<P1> callback(OBJECT *object, void (METHOD::*method)(P1 p1)) { return Callback1<P1>(new Callback1MethodAction<OBJECT, void (METHOD::*)(P1 p1), P1>(object, method)); }
template <class P1, class P2> struct Callback2Action { virtual void Execute(P1 p1, P2 p2) = 0; virtual ~Callback2Action() {} }; template <class OBJECT, class METHOD, class P1, class P2> struct Callback2MethodAction : public Callback2Action<P1, P2> { OBJECT *object; METHOD method; void Execute(P1 p1, P2 p2) { (object->*method)(p1, p2); } Callback2MethodAction(OBJECT *object, METHOD method) : object(object), method(method) {} }; template <class P1, class P2> class Callback2{ public: explicit Callback2(Callback2Action <P1, P2> *newaction) { action = newaction; } Callback2() { action = NULL; } ~Callback2(); Callback2& operator=(const Callback2& c); Callback2(const Callback2& c); void Execute(P1 p1, P2 p2) const { if(action) action->Execute(p1, p2); } void operator()(P1 p1, P2 p2) const { Execute(p1, p2); } private: Callback2Action<P1, P2> *action; }; template <class P1, class P2> Callback2<P1, P2>& Callback2<P1, P2>::operator=(const Callback2& c) { action = c.action; return *this; } template <class P1, class P2> Callback2<P1, P2>::Callback2(const Callback2& c) { action = c.action; } template <class P1, class P2> Callback2<P1, P2>::~Callback2() { } template <class OBJECT, class METHOD, class P1, class P2> Callback2<P1, P2> callback(OBJECT *object, void (METHOD::*method)(P1 p1, P2 p2)) { return Callback2<P1, P2>(new Callback2MethodAction<OBJECT, void (METHOD::*)(P1 p1, P2 p2), P1, P2>(object, method)); }
class Girl { public: void Shopping() { cout << "I want to shopping" << endl; WhenShopping(); WhenBuy("fruits"); WhenBuy("chocolate"); WhenPay(20, 16); } void Swimming() { cout << "I want to swimming" << endl; WhenSwimming(); } Callback WhenShopping; Callback WhenSwimming; Callback1<string> WhenBuy; Callback2<int, int> WhenPay; }; class Boy { public: void Bind(Girl* girl) { girl->WhenShopping = callback(this, &Boy::OnShopping); girl->WhenSwimming = callback(this, &Boy::OnSwimming); girl->WhenBuy = callback(this, &Boy::OnBuy); girl->WhenPay = callback(this, &Boy::OnPay); } private: void OnShopping() {cout << "I know she is shopping" << endl;} void OnSwimming() {cout << "I know she is swimming" << endl;} void OnBuy(string thing) {cout << "She buy " << thing << endl;} void OnPay(int a, int b) {cout << "She pay " << a << " " << b << endl;} };