Posted on May 22nd, 2007 at 23:16 by fr3@K
Preamble
Microsoft 的 MFC 是最早被大量採用 (massive adoption) 的 C++ library 之一. 等到我開始接觸 C++ Standard Library 這東西都已經是玩了兩年 MFC 以後的事. 還記得, 從一開始對 MFC 的讚嘆與擁抱, 幾年後對它的不屑, 到更後來的理解 (理解不好其實也是有原因的).
即便不少 programmer 知道 MFC 是一套瑕疵遍佈的 library, 可能也知道那些地方有問題. 但它以及部份其他 library 聯手對於更多 C++ programmer 造成的傷害已經留下不容易抹滅的痕跡. 它讓許多 programmer 以為這些東西本來就該這樣 (that’s the way things supposed to be), 當有一天這些被誤導的 programmer 有機會可以選擇另一套 library 或是自行設計的時候, 很容易就陷入 MFC 帶給他們已先入為主的錯誤觀念.
Avoid Passing Pointers as Parameters When You Can
在需要被使用者傳入 struct/class 時, MFC 的 function 在 parameter 上大都 (全都?) 選擇接受 pointer 而非 reference. 它幾乎完全忽略決定一個 function parameter 要被定義為 pointer 或 reference 最重要的一點 - 傳入 NULL 的有效語意. 最簡單決定的法則是如果傳入 NULL 會導致 undefined behavior 或不恰當的結果 (如 assertion failure) 那麼就接受 reference. 這會帶來兩個明顯的好處. 首先, 由於 C++ 沒有所謂的 null reference, programmer 都知道 function parameter 為 reference 的語意就是不接受 NULL. 第二, 如果有人 dereference 一個 NULL pointer 當 function parameter 傳遞, 會在執行時期導致程式 crash 在 caller1 (呼叫該 function 的程式). 這比 assertion failure 發生在 callee (被呼叫的 function) 好多了. 畢竟錯誤是 caller 導致.
Try Harder to Avoid Inheritance
我一直懷疑, 許多 C++ thread library 的設計要求 client 以繼承的方式使用, 是因為受到 MFC 的 class CWinThread 以及 Java 的 class Thread 與 interface Runnable 影響. 例如這些 thread class:
- GNU 的 Common C++ 的 class Thread,
- Jori Liesenborgs 的 JThread,
- SourceForge 上的 C++ Threads 的 class Pthread 以及
- Code Project 的 A C++ Thread Class, 等等
想像一下以下這個簡單的狀況. 要被平行處理的 algorithm 早被寫成一個 function 準備好被使用. 但為了使用上述這些 thread class, 使用者必須另外寫個 class 來繼承 thread class 並與 algorithm 一起打成一包使用. 糟糕的是, 繼承可說是 C++ 提供的 language features 裡面能對 code 增加最大相依性的單一功能2. 相對的, Boost.Thread 就只單純的抽象了一種能夠被平行執行, 叫做 thread 的單元. 當被執行的 algorithm 不需要 user input (parameter) 時, 只需要把該 algorithm 當作 parameter 餵給 class boost::thread 的 constructor. 在 algorithm 需要 user input 時, 可以搭配 Boost.Bind 使用, 就地產生將 algorithm 與 user input 綁在一起被執行的 functor. 讓程式不但更簡潔優雅, 也讓相依性降到極低.
如果你是個 library writer, 要是你的 class 能以 component class 的方式呈現, 請避免以 base class 的方式實現. 如果你是位 application writer, 使用 component-based library 常常也會是比 framework-based library 更好的選擇.
![]() |
|
| Previous Post « Happy Birthday, My Dearest Brother « |
Next Post » 給留言朋友的 Mini HTML 教學與建議 » |








對對對~~~
我對於類MFC 中所提供的 thread class 也有這樣的感覺
我有自己寫一個 thread template class 後來發現我的想法與 boost.thread 中的類似。只不過boost漂亮多了,我的threas 還要自己寫一個 function object 然後於建立thread 時帶入這個object,這function object 就是我的thread 要去呼叫的他來做些該做的事。我還分兩種1.單次的 2.loop的。
loop thread 就像下面這樣—
== .h file ==
blr::thread::thread_handle m_thread_handle;
== .cpp ==
class get_data_opr : blr::thread::func_obj{
….
void operator () (HANDLE exit_event){…做些摸魚打混的事…}
….
}
//在某 xxDlg::OnInitDialog()
blr::thread::loop_tthread thread;
m_thread_handle = thread(get_data_opr(this), 50, 0);
//在某 xxDlg::OnClose()
m_thread_handle.end();
這樣不需要有一個 member 去參考或指到一個 operator function,因為 class get_data_opr 有 get_data_opr& operator = (get_data_opr& o);
Comment by 烤布雷 — May 24, 2007 @ 0:32