当前位置: 首页 > news >正文

最大的房产网站深圳品牌网站制作平台

最大的房产网站,深圳品牌网站制作平台,微网站 pc端网站开发,wordpress评论显示楼层转载 C实现的委托机制 1.引言 下面的委托实现使用的MyGUI里面的委托实现#xff0c;MyGUI是一款强大的GUI库#xff0c;想理解更多的MyGUI信息#xff0c;猛击这里http://mygui.info/ 最终的代码可以在这里下载#xff1a;http://download.csdn.net/detail/gouki04/364132…转载 C实现的委托机制 1.引言 下面的委托实现使用的MyGUI里面的委托实现MyGUI是一款强大的GUI库想理解更多的MyGUI信息猛击这里http://mygui.info/  最终的代码可以在这里下载http://download.csdn.net/detail/gouki04/3641328  我们的目标是要实现一个跟.NET几乎完全一样的委托使用简单支持多播可以添加删除委托。同时支持C的普通函数、模板函数、类成员函数类的静态成员函数并且支持多态。使用方式如下   // 普通函数  void normalFunc(){ cout  func1  endl; }  class Base  {  public:  // 类成员函数  void classFunc(){ cout  Base func1  endl; }  };  int main()  {  Base b;  CMultiDelegate myDelegate;  myDelegate  newDelegate(normalFunc);  myDelegate  newDelegate(b, Base::classFunc);  myDelegate(); // 此时会调用normalFunc和classFunc  myDelegate - newDelegate(b, Base::classFunc);  myDelegate(); // 此时会调用normalFunc  return 0;  }       2.实现无参函数委托 要实现委托首先要解决的是封装C中的函数指针。因为在C中普通函数指针和类成员函数指针是完全不一样的。如下例子   class CMyClass  {  public:      void func(int);  };  // 定义一个指向CMyClass类型参数列表为(int)返回值为void的函数指针  typedef void (CMyClass::*ClassMethod) (int); // 注意定义时使用了特殊的运算符::*     那么此函数指针只能指向CMyClass类型的成员函数不能指向其他类或者普通函数 类成员函数指针不能直接调用要通过一个类实例来调用如下   CMyClass *object  new CMyClass;  ClassMethod method  CMyClass::func;  (object-*method)(5); // 注意调用时使用了特殊运算符-*     那么如何封装呢我们先来定义下接口吧 为了简单起见下面的实现都是以无参函数为例后续会讲到如何支持任意参数   class IDelegate  {  public:      virtual ~IDelegate() { }      virtual bool isType(const std::type_info _type)  0;      virtual void invoke()  0;      virtual bool compare(IDelegate *_delegate) const  0;  };     IDelegate类的接口很少也很简单必要接口只有一个就是invoke用于触发函数 但为了可以方便管理使用了isType和compare函数来进行相等判断。 下面是封装的普通函数指针     class CStaticDelegate : public IDelegate  {  public:      typedef void (*Func)();      CStaticDelegate(Func _func) : mFunc(_func) { }      virtual bool isType( const std::type_info _type) { return typeid(CStaticDelegate)  _type; }      virtual void invoke() { mFunc(); }      virtual bool compare(IDelegate *_delegate) const      {          if (0  _delegate || !_delegate-isType(typeid(CStaticDelegate)) ) return false;          CStaticDelegate * cast  static_castCStaticDelegate*(_delegate);          return cast-mFunc  mFunc;      }  private:      Func mFunc;  };     可以看到CStaticDelegate只是简单地封装了普通函数指针代码也非常简单 类的某些成员函数如isType和compare使用了RTTI 对C的动态类型判断不熟的可以猛击这里http://blog.csdn.net/gouki04/article/details/6796173 好了注意了下面开始封装类成员函数指针   templateclass T  class CMethodDelegate : public IDelegate  {  public:      typedef void (T::*Method)();      CMethodDelegate(T * _object, Method _method) : mObject(_object), mMethod(_method) { }      virtual bool isType( const std::type_info _type) { return typeid(CMethodDelegate)  _type; }      virtual void invoke()      {          (mObject-*mMethod)();      }      virtual bool compare(IDelegate *_delegate) const      {          if (0  _delegate || !_delegate-isType(typeid(CMethodDelegate)) ) return false;          CMethodDelegate* cast  static_castCMethodDelegate* (_delegate);          return cast-mObject  mObject  cast-mMethod  mMethod;      }  private:      T * mObject;      Method mMethod;  };     首先解释一下因为类成员函数指针与类的类型有关不同类的成员函数指针是不一样的。 要解决类型不同很简单使用模板就行。 代码跟CStaticDelegate基本一样下面稍微解释一下 CMethodDelegate类主要封装了一个类实例指针以及类成员函数的指针 这样在invoke时就不要额外的通过一个类实例了 要注意一点compare函数的实现中相等判定是类实例以及类函数指针都一样。 也就是说就算是指针同一个成员函数但实例不同委托就不同 为了方便使用定义函数newDelegate来创建委托使用的函数   inline IDelegate* newDelegate( void (*_func)() )  {      return new CStaticDelegate(_func);  }  templateclass T  inline IDelegate* newDelegate( T * _object, void (T::*_method)() )  {      return new CMethodDelegateT(_object, _method);  }     至此对C函数指针的封装就完成了不难吧。 下面就是委托的实现了   class CMultiDelegate  {  public:      typedef std::listIDelegate* ListDelegate;      typedef ListDelegate::iterator ListDelegateIterator;      typedef ListDelegate::const_iterator ConstListDelegateIterator;      CMultiDelegate () { }      ~CMultiDelegate () { clear(); }      bool empty() const      {          for (ConstListDelegateIterator iter  mListDelegates.begin(); iter!mListDelegates.end(); iter)          {              if (*iter) return false;          }          return true;      }      void clear()      {          for (ListDelegateIterator itermListDelegates.begin(); iter!mListDelegates.end(); iter)          {              if (*iter)              {                  delete (*iter);                  (*iter)  0;              }          }      }      CMultiDelegate operator(IDelegate* _delegate)      {          for (ListDelegateIterator itermListDelegates.begin(); iter!mListDelegates.end(); iter)          {              if ((*iter)  (*iter)-compare(_delegate))              {                  delete _delegate;                  return *this;              }          }          mListDelegates.push_back(_delegate);          return *this;      }      CMultiDelegate operator-(IDelegate* _delegate)      {          for (ListDelegateIterator itermListDelegates.begin(); iter!mListDelegates.end(); iter)          {              if ((*iter)  (*iter)-compare(_delegate))              {                  if ((*iter) ! _delegate) delete (*iter);                  (*iter)  0;                  break;              }          }          delete _delegate;          return *this;      }      void operator()( )      {          ListDelegateIterator iter  mListDelegates.begin();          while (iter ! mListDelegates.end())          {              if (0  (*iter))              {                  iter  mListDelegates.erase(iter);              }              else              {                  (*iter)-invoke();                  iter;              }          }      }  private:      CMultiDelegate (const CMultiDelegate _event);      CMultiDelegate operator(const CMultiDelegate _event);  private:      ListDelegate mListDelegates;  };     仔细理解下CMultiDelegate类的实现代码都不深奥。 比较重要的是3个函数 -()运算符的重载函数  用于添加一个委托函数 - 用于去掉一个委托函数 () 用于触发委托函数 差不多就是普通的stl容器使用了。 这里要重点说明的一点是大家仔细看  函数的实现中   if ((*iter)  (*iter)-compare(_delegate))  {  delete _delegate; // 如果该委托函数已经被添加了则delete掉外部的_delegate  return *this;  }     为什么要delete掉外部的指针呢 因为C的内存泄露一直是个麻烦事所以MyUGI的委托里所有的委托函数统一由Delegate本身管理 外部不要自己new或delete委托函数也不要保存一个委托函数Delegate本身会管理好的。 建议像如下使用   CMultiDelegate myDelegate;  myDelegate  newDelegate(normalFunc);  myDelegate - newDelegate(normalFunc);     而不建议像如下使用   CMultiDelegate myDelegate;  IDelegate* delegateFunc  newDelegate(normalFunc);  myDelegate  delegateFunc;  myDelegate - delegateFunc;     上面2种方法都没错都不会造成内存泄露 你可能会觉得第2种方法减少new的次数比第一种方法更好。其实不然因为第2种方法有个很大的隐患   myDelegate - delegateFunc; // 在这一步delegateFunc所指向的空间已经被释放掉了在-函数里面     所以如果你后面又想将delegateFunc添加到myDelegate里面时你就不能再这样用了   myDelegate  delegateFunc; // 错误因为delegateFunc的空间已经被释放了     你得重新new一个 delegateFunc  newDelegate(normalFunc); myDelegate  delegateFunc; 相信你不会愿意这样做的因为这种方法很容易造成内存泄露或者崩溃 现在你应该可以明白 - 函数是怎么释放委托函数内存了吧。   1.实现任意参数的函数委托 按上一篇文章的方法你已经可以使用无参数的函数委托了。当然这远远不够。要实现任意参数的函数委托这里的任意参数包括任意个数和任意类型。任意类型这个容易解决使用模板就行但任意参数个数呢 注最终的实现代码可以在这里下载http://download.csdn.net/detail/gouki04/3641328 只能不同个数各实现一个类如   // 单参函数委托  templatetypename TP1  class CMultiDelegate1{};  // 双参函数委托  templatetypename TP1, typename TP2  class CMultiDelegate2{};     注意类名是不一样的分别为CMultiDelegate1和CMultiDelegate2 C里面类名相同但模板参数个数不同是会当成一个类对待的所以那样编译不过的 这样是不是很麻烦呢 不是很麻烦是相当麻烦。因为不单单是CMultiDelegate要实现多个参数的版本 连IDelegate、CStaticDelegate和CMethodDelegate都要实现对应的多个参数的版本 其实所有版本的内部实现几乎一样下面给出双参函数的版本   templatetypename TP1, typename TP2  class IDelegate2  {  public:      virtual ~IDelegate2() { }      virtual bool isType( const std::type_info _type)  0;      virtual void invoke( TP1 p1, TP2 p2 )  0;      virtual bool compare( IDelegate2typename TP1, typename TP2 *_delegate) const  0;  };  templatetypename TP1, typename TP2  class CStaticDelegate2 : public  IDelegate2typename TP1, typename TP2  {  public:      typedef void (*Func)( TP1 p1, TP2 p2 );      CStaticDelegate2 (Func _func) : mFunc(_func) { }      virtual bool isType( const std::type_info _type) { return typeid( CStaticDelegate2typename TP1, typename TP2 )  _type; }      virtual void invoke( TP1 p1, TP2 p2 )      {          mFunc( p1, p2 );      }      virtual bool compare( IDelegate2typename TP1, typename TP2 *_delegate) const      {          if (0  _delegate || !_delegate-isType(typeid(CStaticDelegate2 typename TP1, typename TP2)) ) return false;          CStaticDelegate2 typename TP1, typename TP2 * cast  static_castCStaticDelegate2 typename TP1, typename TP2 *(_delegate);          return cast-mFunc  mFunc;      }      virtual bool compare(IDelegateUnlink * _unlink) const { return false; }  private:      Func mFunc;  };  template typename T, typename TP1, typename TP2  class CMethodDelegate2 : public  IDelegate2 typename TP1, typename TP2  {  public:      typedef void (T::*Method)( TP1 p1, TP2 p2 );      CMethodDelegate2(T * _object, Method _method) : mObject(_object), mMethod(_method) { }      virtual bool isType( const std::type_info _type) { return typeid( CMethodDelegate2 T, TP1, TP2 )  _type; }      virtual void invoke( TP1 p1, TP2 p2 )      {          (mObject-*mMethod)( p1, p2 );      }      virtual bool compare(  IDelegate2 typename TP1, typename TP2  * _delegate) const      {          if (0  _delegate || !_delegate-isType(typeid(CMethodDelegate2 T, TP1, TP2)) ) return false;          CMethodDelegate2 T, TP1, TP2  * cast  static_cast  CMethodDelegate2 T, TP1, TP2  * (_delegate);          return cast-mObject  mObject  cast-mMethod  mMethod;      }  private:      T * mObject;      Method mMethod;  };  template   typename TP1, typename TP2  inline  delegates::IDelegate2 typename TP1, typename TP2  * newDelegate( void (*_func)( TP1 p1, TP2 p2 ) )  {      return new delegates::CStaticDelegate2 typename TP1, typename TP2  (_func);  }  template typename T, typename TP1, typename TP2  inline  delegates::IDelegate2 typename TP1, typename TP2  * newDelegate( T * _object, void (T::*_method)( TP1 p1, TP2 p2 ) )  {      return new delegates::CMethodDelegate2  T, TP1, TP2  (_object, _method);  }  template   typename TP1, typename TP2  class CMultiDelegate2  {  public:      typedef IDelegate2 typename TP1, typename TP2  IDelegate;      typedef typename std::listIDelegate* ListDelegate;      typedef typename ListDelegate::iterator ListDelegateIterator;      typedef typename ListDelegate::const_iterator ConstListDelegateIterator;      CMultiDelegate2 () { }      ~CMultiDelegate2 () { clear(); }      bool empty() const      {          for (ConstListDelegateIterator iter  mListDelegates.begin(); iter!mListDelegates.end(); iter)          {              if (*iter) return false;          }          return true;      }      void clear()      {          for (ListDelegateIterator itermListDelegates.begin(); iter!mListDelegates.end(); iter)          {              if (*iter)              {                  delete (*iter);                  (*iter)  0;              }          }      }      CMultiDelegate2  typename TP1, typename TP2  operator(IDelegate* _delegate)      {          for (ListDelegateIterator itermListDelegates.begin(); iter!mListDelegates.end(); iter)          {              if ((*iter)  (*iter)-compare(_delegate))              {                  delete _delegate;                  return *this;                  //MYGUI_ASSERT(false, dublicate delegate);              }          }          mListDelegates.push_back(_delegate);          return *this;      }      CMultiDelegate2  typename TP1, typename TP2  operator-(IDelegate* _delegate)      {          for (ListDelegateIterator itermListDelegates.begin(); iter!mListDelegates.end(); iter)          {              if ((*iter)  (*iter)-compare(_delegate))              {                  if ((*iter) ! _delegate) delete (*iter);                  (*iter)  0;                  break;              }          }          delete _delegate;          return *this;      }      void operator()( TP1 p1, TP2 p2 )      {          ListDelegateIterator iter  mListDelegates.begin();          while (iter ! mListDelegates.end())          {              if (0  (*iter))              {                  iter  mListDelegates.erase(iter);              }              else              {                  (*iter)-invoke( p1, p2 );                  iter;              }          }      }  private:      CMultiDelegate2 (const CMultiDelegate2  typename TP1, typename TP2  _event);      CMultiDelegate2typename TP1, typename TP2  operator(const CMultiDelegate2typename TP1, typename TP2  _event);  private:      ListDelegate mListDelegates;  };     当然放心啦不会让大家将不同参数的版本各写一遍的 下面要介绍的是MyGUI的解决方法一个利用预编译和头文件重复编译的方法很有意思的 我们一般写头文件时都会加上防止头文件重复编译的代码如   #ifndef __XXX_H__  #define __XXX_H__  // ..类声明等  #endif     这里我们就要反其道而行去掉防止重复编译的代码然后重复包含这个头文件但每次其编译的都是不同参数个数的版本 第一次编译的是无参的第二次是单参的第三次是双参.....一直到你想要支持的参数个数 那怎么让其每次编译的都不同呢 答案就是使用强大的预编译宏 下面给出单参的IDelegate的例子 首先定义以下宏   #define DELEGATE_TEMPLATE template  #define DELEGATE_TEMPLATE_PARAMS typename TP1  #define DELEGATE_TEMPLATE_ARGS TP1 p1  #define MYGUI_I_DELEGATE IDelegate1     那么下面这段代码就会编译出单参的IDelegate版本   DELEGATE_TEMPLATE   DELEGATE_TEMPLATE_PARAMS  class MYGUI_I_DELEGATE  {  public:      virtual ~MYGUI_I_DELEGATE() { }      virtual bool isType( const std::type_info _type)  0;      virtual void invoke( DELEGATE_PARAMS )  0;      virtual bool compare(  MYGUI_I_DELEGATE DELEGATE_TEMPLATE_ARGS  * _delegate) const  0;  };     神奇吧这里使用的可以说是宏实现的多态。 在这段代码编译完了之后将所有宏都undefine掉如   #undef DELEGATE_TEMPLATE  #undef DELEGATE_TEMPLATE_PARAMS  #undef DELEGATE_TEMPLATE_ARGS  #undef MYGUI_I_DELEGATE     再重新定义双参版本的如   #define DELEGATE_TEMPLATE template  #define DELEGATE_TEMPLATE_PARAMS typename TP1, typename TP2  #define DELEGATE_TEMPLATE_ARGS TP1 p1, TP2 p2  #define MYGUI_I_DELEGATE IDelegate2     那么编译出来的就是双参的版本了 使用这种方法就可以将其他的如CStaticDelegate、CMethodDelegate和CMultiDelegate的各种版本都实现了 而你要做的仅是重新define下那些宏就行了够方便了吧。 下一篇文章将会介绍MyGUI实现的一些辅助类如单委托和DelegateUnlink。并给出一个测试例子测试该委托机制对C各种函数的支持。     1.引言 按上一篇文章的方法你已经可以使用任意参数的函数委托了。这里介绍下MyGUI实现的两个辅助类CDelegate类和IDelegateUnlink。如果你不为了深入了解MyGUI的委托实现可以跳过此处。CDelegate即为单委托实际效果跟函数指针差不多于CMultiDelegate的区别在于其不支持多播。而IDelegateUnlink类主要是在CMultiDelegate中使用在多播下一次性去掉自身的所有委托。2.单委托 // 无参的单委托实现  class CDelegate  {  public:      typedef CDelegate IDelegate;          CDelegate () : mDelegate(0) { }      CDelegate (const CDelegate _event)      {          // 在拷贝构造时将被拷贝的委托去掉即委托只存在一份          mDelegate  _event.mDelegate;          const_castCDelegate(_event).mDelegate  0;      }      ~CDelegate () { clear(); }          bool empty() const { return mDelegate  0; }          void clear()      {          if (mDelegate)          {              delete mDelegate;              mDelegate  0;          }      }          CDelegate  operator(IDelegate* _delegate)      {          delete mDelegate;          mDelegate  _delegate;          return *this;      }          CDelegate  operator(const CDelegate _event)      {          // 在赋值时将右值的委托去掉即委托只存在一份          delete mDelegate;          mDelegate  _event.mDelegate;          const_castCDelegate(_event).mDelegate  0;              return *this;      }          void operator()( )      {          if (mDelegate  0) return;          mDelegate-invoke( );      }      private:      IDelegate * mDelegate;  };   可以看到单委托只实现了 运算符没有实现 运算符。而且在赋值时会将原委托去掉确保只有一份委托。其实单委托跟普通函数指针差不多在使用单委托的地方可以换成使用普通函数指针。3.断开委托 // 断开委托的基类  class IDelegateUnlink  {  public:      virtual ~IDelegateUnlink() { }          IDelegateUnlink() { m_baseDelegateUnlink  this; }      bool compare(IDelegateUnlink * _unlink) const { return m_baseDelegateUnlink  _unlink-m_baseDelegateUnlink; }      private:      IDelegateUnlink * m_baseDelegateUnlink;  };   所谓断开委托只能用在多重委托即CMultiDelegate中可以断开自身与其相连的所有委托。使用方法就在将自身的类从IDelegateUnlink派生然后使用CMultiDelegate中的clear函数即可断开委托。在下面会有例子说明。4.测试 /* 测试Delegate对不同函数的支持  * 可以参考下不同函数的使用方式  */  #include delegate.h  #include iostream      using namespace std;      // 普通函数1  void func(int a, int b)  {      cout  func(  a  ,   b  )  endl;  }      // 普通函数2  void func2(int a, int b)  {      cout  func2(  a  ,   b  )  endl;  }      // 普通类  class NormalClass  {  public:      // 类的普通成员函数      void normalFunc(int a, int b)      {          cout  NormalClass::normalFunc(  a  ,   b  )  endl;      }  };      // 实现了IDelegateUnlink的类  class BaseUnlinkClass : public delegates::IDelegateUnlink  {  public:      // 类的虚函数      virtual void virFunc(int a, int b)      {          cout  BaseUnlinkClass::virFunc(  a  ,   b  )  endl;      }          // 类的普通成员函数      void normalFunc(int a, int b)      {          cout  BaseUnlinkClass::normalFunc(  a  ,   b  )  endl;      }  };      class DerivedClass : public BaseUnlinkClass  {  public:      // 类的虚函数      virtual void virFunc(int a, int b)      {          cout  DerivedClass::virFunc(  a  ,   b  )  endl;      }          // 类的静态成员函数      static void staticFunc(int a, int b)      {          cout  DerivedClass::staticFunc(  a  ,   b  )  endl;      }  };      // 模板函数  templateclass T  void TFunc(T a, T b)  {      cout  TFunc(  a  ,   b  )  endl;  }      int main()  {      BaseUnlinkClass *baseUnlinkClass  new BaseUnlinkClass;      DerivedClass *derivedClass  new DerivedClass;      NormalClass *normalClass  new NormalClass;            // 定义委托      typedef delegates::CMultiDelegate2int, int EvenetHandler;      EvenetHandler event;          // 添加普通函数      event  newDelegate(func);      event  newDelegate(func2);          // 添加类的普通成员函数      event  newDelegate(normalClass, NormalClass::normalFunc);      event  newDelegate(baseUnlinkClass, BaseUnlinkClass::normalFunc);          // 添加类的虚函数      event  newDelegate(baseUnlinkClass, BaseUnlinkClass::virFunc);      event  newDelegate(derivedClass, DerivedClass::virFunc);      // 注意在多态下使用基类指针时函数指针要用基类的函数指针不能用派生类的      // 但是在调用时会响应多态也就是会调用派生类的虚函数      event  newDelegate((BaseUnlinkClass*)derivedClass, BaseUnlinkClass::virFunc);          // 添加类的静态成员函数      event  newDelegate(DerivedClass::staticFunc);          // 添加模板函数      event  newDelegate(TFuncint);            // 触发事件      event(1, 2);      cout  endl;          // 去掉函数      event - newDelegate(func);          // 去掉baseUnlinkClass所有的函数      event.clear(baseUnlinkClass);          // 去掉derivedClass所有的函数      // 注意静态成员函数staticFunc不会去掉      event.clear(derivedClass);          //event.clear(normalClass);      // 错误调用normalClass不是IDelegateUnlink的派生类      // 不能使用clear去掉自身的函数      // 应该使用如下方法      event - newDelegate(normalClass, NormalClass::normalFunc);            // 触发事件      event(2, 3);      cout  endl;          return 0;  }   转载于:https://www.cnblogs.com/zhoug2020/p/6592089.html
http://www.yutouwan.com/news/472540/

相关文章:

  • 网站建设公司画册wordpress里的模板怎么用
  • 网站建设作业做一个简单的网站国外模板wordpress
  • 建设工程网上质检备案网站wordpress 4.7 模板
  • 福州网站建设公司手机怎么登录网页版微信
  • 翠竹林wordpress主题北京seo优化技术
  • 网站建设需要些什么东西成都微信网站建设报价单
  • 闽侯网站建设网站开发可以申请著作权吗
  • 旅行社网站策划wordpress用户安全
  • 2003年北京网站建设上市公司协会网站建设汇报
  • 网站建设免费空间注册导航电影网站的设计与实现论文
  • 做美食推广的网站网页制作视频代码
  • 建站程序大全建设厅网站如何查询企业信息
  • wordpress 建网站 vpn舜江建设集团官方网站
  • 义乌论坛网站建设网站技术支持 新锐网络
  • 做农业种子的网站高端建站的公司
  • 天台做网站it培训机构包就业
  • 建设网站费用主要包括哪些内容wordpress嵌入百度地图
  • wordpress 简书主题山东seo
  • 网站系统架构图国外平面设计欣赏网站
  • 湖南网站托管宁夏网站建设哪个好
  • 网站开发合同是否是技术合同重庆重庆网站建设
  • 建设网站空间合同网络推广SEO优化网站建设
  • 秦皇岛市网站建设网站备案都审核什么
  • 制作网站哪里好搜索推广和信息流推广的区别
  • 可以做雷达图的网站做外贸大大小小的网站有哪些
  • 免费seo网站优化工具免费网站建站手机
  • 怎么建设国外免费网站网站建设找客户
  • 厦门网站流量优化价格电脑做h5的软件有哪些
  • 网站如何做搜索引擎优化新手如何做网络推广
  • 青岛网站建设制作公司我想找一个电销外包团队