C 实现委托和消息反馈模板

2008-02-23 05:25:12来源:互联网 阅读 ()

新老客户大回馈,云服务器低至5折

 摘要:本文简单介绍并比较了用于实现消息反馈的几种常见技术,其中周详介绍了利用C 模板技术来实现类型安全的委托的要点和限制,能够作为理解qt/gtk 等UI库的信号反馈机制的入门文章。

  正文:我写过不少C 程式,写过库也写过客户程式。一般库都会提供一些好用的类供客户程式使用,不少库还能够让客户程式响应库内的某些事件。比如MFC/ATL/VCL提供消息响应,很多ActiveX提供自定义消息响应,甚至是系统底层的中断调用都能够列入这个范畴。然而,正是以上这些“反向”的调用让我觉得很烦恼。

  继承 多态

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

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

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

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

struct SocketEventHandler {
virtual void OnRecv() { /* ... */ }
virtual void OnSend() { /* ... */ }
};
struct Socket {
void set_handler( SocketEventHandler* h ) { handler_ = h; }
private:
SocketEventHandler* handler_;
};
struct MyHandler : SocketEventHandler {
void OnRecv() { ... }
};
Socket s;
MyHandler h;
s.set_handler( &h );

  突然之间,我感到一阵迷茫,很渴望一种简单明确的表达方法。丢开继承,我们更有什么把戏?我不禁想起了c时代的回调函数……

  回调函数(CallBack)

  很简单,就是个函数指针。刚才的OnRecv能够写成这样

struct Socket {
void OnRecv() { if(OnRecvHandle!=NULL) OnRecvHandle(); }
void (*OnRecvHandle) ();
};

  客户程式只需要编写一个MyOnRecv函数,并且赋值给OnRecvHandle就能够了

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


  疑问:很简单,无需继承类就能够处理,而且随时能够替换不同的处理函数。其实多态的本质也是函数指针,只但是多态是用vtable统一管理函数指针。回调函数要特别注意函数指针是否为空的问题,因此最好外面在包装一层判断过程。回调函数最大问题在于类型不安全,显式指针这东西……不说也罢……翻了一下智能指针和模版,我发现了一根稻草……



[1] [2] [3] 下一页

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇: 浅谈C 中的内存管理

下一篇: C 消息连接的一种系统方法

热门词条
热门标签