龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > 软件开发 > C/C++开发 >

细说C++委托和消息反馈模板(1)

时间:2011-04-12 23:18来源:未知 作者:admin 点击:
分享到:
C++ 实现 委托 和 消息反馈 模板: 继承+多态 乍一看是理所当然的选择,库中的类把响应处理函数设置为虚函数,客户程序可以继承这个类并且重载响应函数。以某个Socket类为例,可以提

C++实现委托消息反馈模板:

继承+多态

乍一看是理所当然的选择,库中的类把响应处理函数设置为虚函数,客户程序可以继承这个类并且重载响应函数。以某个Socket类为例,可以提供一个OnRecv函数用来响应网络数据包到达的处理。客户程序只需要重载OnRecv并进行自己的处理就可以了。

  1. struct Socket { // base class  
  2. virtual void OnRecv();  
  3. };  
  4. stuct MySocket { // your event-handle class  
  5. virtual void OnRecv() { /* do sth here ... */ }  

疑问:很多时候这样做实在很烦,特别是做小程序的时候,或者需要快速做原型的时候,一眼望去小小的程序一上来就继承了一大堆东西,颇为不爽。只是想着能省事一点,希望能像那些脚本语言一样快速绑定消息响应,而不是以继承开始工作——我已经害怕看到长长的类继承树了,很多时候根本不必要继承整个类;又或者某些类只提供一个接口而不是具体的类又或者需要多重继承,处理都有一定麻烦;最麻烦的莫过于有时候需要改变响应处理,难道继承好几个下来么——这么多虚表也是浪费啊。

点评:为了使用Socket就必须继承Socket,这可以说是Socket的设计的问题。如果需要实现类似的功能的话,可以写成如下,虽然和继承 Socket 没有多少本质的差别,不过确实把消息处理类和Socket的实现扯开了。

  1. struct SocketEventHandler {  
  2. virtual void OnRecv() { /* ... */ }  
  3. virtual void OnSend() { /* ... */ }  
  4. };  
  5. struct Socket {  
  6. void set_handler( SocketEventHandler* h ) { handler_ = h; }  
  7. private:  
  8. SocketEventHandler* handler_;  
  9. };  
  10. struct MyHandler : SocketEventHandler {  
  11. void OnRecv() { ... }  
  12. };  
  13. Socket s;  
  14. MyHandler h;  
  15. s.set_handler( &h ); 

丢开继承,我们有没有一种简单明确的表达方法呢?我不禁想起了c时代的回调函数……

回调函数(CallBack)

非常简单,就是一个函数指针。刚才的OnRecv可以写成这样

  1. struct Socket {  
  2. void OnRecv() { if(OnRecvHandle!=NULL) OnRecvHandle(); }  
  3. void (*OnRecvHandle) ();  
  4. };  

客户程序只需要编写一个MyOnRecv函数,并且赋值给OnRecvHandle就可以了

  1. void MyOnRecv(); // your event-handle function  
  2. Socket foo;  
  3. foo.OnRecvHandle = MyOnRecv; 

疑问:非常简单,不需要继承类就可以处理,而且随时可以替换不同的处理函数。其实多态的本质也是函数指针,只不过多态是用vtable统一管理函数指针。回调函数要特别注意函数指针是否为空的问题,因此最好外面在包装一层判断过程,回调函数最大问题在于类型不安全。


精彩图集

赞助商链接