Chinaunix首页 | 论坛 | 博客

分类: C/C++

2012-03-13 21:59:48

C++实现的委托机制(三)

 

作者:gouki04(啊古)  撰写日期:2011-10-08

博客链接:http://blog.csdn.net/gouki04

 

1.引言

    按上一篇文章的方法,你已经可以使用任意参数的函数委托了。这里介绍下MyGUI实现的两个辅助类,CDelegate类和IDelegateUnlink。如果你不为了深入了解MyGUI的委托实现,可以跳过此处。CDelegate即为单委托,实际效果跟函数指针差不多,于CMultiDelegate的区别在于其不支持多播。而IDelegateUnlink类主要是在CMultiDelegate中使用,在多播下一次性去掉自身的所有委托。

注:最终的实现代码可以在这里下载:

 

2.单委托


点击(此处)折叠或打开

  1. // 无参的单委托实现
  2. class CDelegate
  3. {
  4. public:
  5.     typedef CDelegate IDelegate;
  6.     CDelegate () : mDelegate(0) { }
  7.     CDelegate (const CDelegate& _event)
  8.     {
  9.         // 在拷贝构造时,将被拷贝的委托去掉,即委托只存在一份
  10.         mDelegate = _event.mDelegate;
  11.         const_cast<CDelegate&>(_event).mDelegate = 0;
  12.     }
  13.     ~CDelegate () { clear(); }
  14.     bool empty() const { return mDelegate == 0; }
  15.     void clear()
  16.     {
  17.         if (mDelegate)
  18.         {
  19.             delete mDelegate;
  20.             mDelegate = 0;
  21.         }
  22.     }
  23.     CDelegate & operator=(IDelegate* _delegate)
  24.     {
  25.         delete mDelegate;
  26.         mDelegate = _delegate;
  27.         return *this;
  28.     }
  29.     CDelegate & operator=(const CDelegate& _event)
  30.     {
  31.         // 在赋值时,将右值的委托去掉,即委托只存在一份
  32.         delete mDelegate;
  33.         mDelegate = _event.mDelegate;
  34.         const_cast<CDelegate&>(_event).mDelegate = 0;
  35.         return *this;
  36.     }
  37.     void operator()( )
  38.     {
  39.         if (mDelegate == 0) return;
  40.         mDelegate->invoke( );
  41.     }
  42. private:
  43.     IDelegate * mDelegate;
  44. };

    可以看到,单委托只实现了 = 运算符,没有实现 += 运算符。而且在赋值时会将原委托去掉,确保只有一份委托。其实单委托跟普通函数指针差不多,在使用单委托的地方可以换成使用普通函数指针。

 

3.断开委托


点击(此处)折叠或打开

  1. // 断开委托的基类
  2. class IDelegateUnlink
  3. {
  4. public:
  5.     virtual ~IDelegateUnlink() { }

  6.     IDelegateUnlink() { m_baseDelegateUnlink = this; }
  7.     bool compare(IDelegateUnlink * _unlink) const { return m_baseDelegateUnlink == _unlink->m_baseDelegateUnlink; }

  8. private:
  9.     IDelegateUnlink * m_baseDelegateUnlink;
  10. };

    所谓断开委托,只能用在多重委托,即CMultiDelegate中,可以断开自身与其相连的所有委托。使用方法就在将自身的类从IDelegateUnlink派生,然后使用CMultiDelegate中的clear函数即可断开委托,在下面会有例子说明。

 

4.测试


点击(此处)折叠或打开

  1. /* 测试Delegate对不同函数的支持,可以参考下不同函数的使用方式 */
  2. #include "delegate.h"
  3. #include <iostream>

  4. using namespace std;

  5. // 普通函数1
  6. void func(int a, int b)
  7. {
  8.     cout << "func(" << a << ", " << b << ")" << endl;
  9. }

  10. // 普通函数2
  11. void func2(int a, int b)
  12. {
  13.     cout << "func2(" << a << ", " << b << ")" << endl;
  14. }

  15. // 普通类
  16. class NormalClass
  17. {
  18. public:
  19.     // 类的普通成员函数
  20.     void normalFunc(int a, int b)
  21.     {
  22.         cout << "NormalClass::normalFunc(" << a << ", " << b << ")" << endl;
  23.     }
  24. };

  25. // 实现了IDelegateUnlink的类
  26. class BaseUnlinkClass : public delegates::IDelegateUnlink
  27. {
  28. public:
  29.     // 类的虚函数
  30.     virtual void virFunc(int a, int b)
  31.     {
  32.         cout << "BaseUnlinkClass::virFunc(" << a << ", " << b << ")" << endl;
  33.     }

  34.     // 类的普通成员函数
  35.     void normalFunc(int a, int b)
  36.     {
  37.         cout << "BaseUnlinkClass::normalFunc(" << a << ", " << b << ")" << endl;
  38.     }
  39. };

  40. class DerivedClass : public BaseUnlinkClass
  41. {
  42. public:
  43.     // 类的虚函数
  44.     virtual void virFunc(int a, int b)
  45.     {
  46.         cout << "DerivedClass::virFunc(" << a << ", " << b << ")" << endl;
  47.     }

  48.     // 类的静态成员函数
  49.     static void staticFunc(int a, int b)
  50.     {
  51.         cout << "DerivedClass::staticFunc(" << a << ", " << b << ")" << endl;
  52.     }
  53. };

  54. // 模板函数
  55. template<class T>
  56. void TFunc(T a, T b)
  57. {
  58.     cout << "TFunc(" << a << ", " << b << ")" << endl;
  59. }

  60. int main()
  61. {
  62.     BaseUnlinkClass *baseUnlinkClass = new BaseUnlinkClass;
  63.     DerivedClass *derivedClass = new DerivedClass;
  64.     NormalClass *normalClass = new NormalClass;
  65.     
  66.     // 定义委托
  67.     typedef delegates::CMultiDelegate2<int, int> EvenetHandler;
  68.     EvenetHandler event;

  69.     // 添加普通函数
  70.     event += newDelegate(func);
  71.     event += newDelegate(func2);

  72.     // 添加类的普通成员函数
  73.     event += newDelegate(normalClass, &NormalClass::normalFunc);
  74.     event += newDelegate(baseUnlinkClass, &BaseUnlinkClass::normalFunc);

  75.     // 添加类的虚函数
  76.     event += newDelegate(baseUnlinkClass, &BaseUnlinkClass::virFunc);
  77.     event += newDelegate(derivedClass, &DerivedClass::virFunc);
  78.     // 注意在多态下,使用基类指针时,函数指针要用基类的函数指针,不能用派生类的
  79.     // 但是在调用时会响应多态,也就是会调用派生类的虚函数
  80.     event += newDelegate((BaseUnlinkClass*)derivedClass, &BaseUnlinkClass::virFunc);

  81.     // 添加类的静态成员函数
  82.     event += newDelegate(&DerivedClass::staticFunc);

  83.     // 添加模板函数
  84.     event += newDelegate(TFunc<int>);
  85.     
  86.     // 触发事件
  87.     event(1, 2);
  88.     cout << endl;

  89.     // 去掉函数
  90.     event -= newDelegate(func);

  91.     // 去掉baseUnlinkClass所有的函数
  92.     event.clear(baseUnlinkClass);

  93.     // 去掉derivedClass所有的函数
  94.     // 注意静态成员函数staticFunc不会去掉
  95.     event.clear(derivedClass);

  96.     //event.clear(normalClass);
  97.     // 错误调用,normalClass不是IDelegateUnlink的派生类
  98.     // 不能使用clear去掉自身的函数
  99.     // 应该使用如下方法
  100.     event -= newDelegate(normalClass, &NormalClass::normalFunc);
  101.     
  102.     // 触发事件
  103.     event(2, 3);
  104.     cout << endl;

  105.     return 0;
  106. }
阅读(405) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~