现在的位置: 首页 > 综合 > 正文

为什么说MFC是垃圾

2013年04月10日 ⁄ 综合 ⁄ 共 1501字 ⁄ 字号 评论关闭

本来是原创文章,发表与论坛,增加修改了一些东西。

我说MFC设计得不好, MFC最重要的一个class应该是CWnd,对吧?
 

一个CWnd多少个字节? 我记得好像是64(60?)个字节。按照你的理解,可能4个字节的HWND以及最多虚拟函数需要使用的4个字节加起来8个字节就够了(ATL的CWindow只有4个字节,虚函数都没有,消息处理通过多层继承实现正交分解)。但是CWnd为什么有64个字节? 因为CWnd里面什么都有,甚至包括为了COM支持的一个m_xDispatch对象,IUnkonwn指针,派生类对话框需要的返回值等等。总是只要可能需要的全部都在此,完全违背了一个良好的OO设计中高聚集,低偶合的原则,更勿论什么正交分解。我大部分时候使用CWnd的时候不需要和Dispatch什么的打交道,对吧?这个设计好像叫God class,什  么都有,好像一个垃圾桶,一切尽在其中。

其他的我想你也可以找到,再举个例子,MFC的CSocket是不能跨线程使用的,因为他内部使用了一个CWnd对象。OK,这个是封装细节,我无须考虑,但是由于CWnd不能跨线程使用,造成我的CSocket不能跨线程,这就变成一个需要开发者理解的实现细节了。你不看源代码你根本不知道什么原因。可以理解这个是基于Win3.0不支持多线程的遗留代码,但是现在一直没有改进,无论如何作为一个在网络环境中使用的类,竟然不能跨线程使用,不可能是一个好的设计。

 

又例如虽然有CSocket类,但是没有一个对应的CSocketAddress类似的类,OK,你可以使用CSocket::open("localhost", 80)进行网络连接而无须处理sockaddr结构,但是你如果想将localhost, 80转化成一个sockaddr结构就没门,它只能在CSocket中使用,而且必须就是连接open的这个函数,除了最原始的拷贝张贴,你实在无法重用什么东西。提取不够,一个类权限过多。

 

还有好像我记得它的SplitWindow,一个分割窗口的实现,非要绑定到Doc-View上面,结果我的一个简单的对话框程序就无法使用。不是人人都需要Doc-View的。对吧?但是需要split windows的地方很多,结果MFC这个设计非将我绑定到Doc-View上面。跟Delphi中的anchor,dock比起来落后一个世纪。

 

还有很多,例如CString,CString的reference count是线程安全的,但是代价是使用Interlock等函数,虽然代价很少,但是我如果总是在单线程中使用,这个代价我都不应该付出,但是无论如何,这个代码你使用CString都得有。你有什么办法?

 

而且CString使用宏来确定是否wchar还是char也很不合理。例如我的程序编译成unicode版本,但是需要使用ansi string,那么CString好像也无法使用了。

 

MFC以现在的C++观点来看,对C++语言的使用停留在Script级别,对OO的封装理解停留在Visual Basic的级别。我知道有WTL之父,有STL之父的interview,当然C++之父的就不用说了,好像还没有听说MFC之父吧?谁也不愿意当冤大头,丢不起这个人啊。对吧?
 
当然有历史原因。但是你不能因为它当时还凑合能用就认为它永垂不朽吧?或者,认为他就是一个很好的C++类库设计典范吧?
 
总之,某些局部地方,MFC可能有可取之处,特别是它Bug相对来说很少。整体设计,如果不是MS的官方产品,我估计早就在垃圾箱了,在很多反面违反了,即使是作为OO对象对象理论来说的一些基本的设计准则。
 

【上篇】
【下篇】