爲什麼說MFC是垃圾

我說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對象對象理論來說的一些基本的設計準則。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章