在建構函式內的工作
避免在建構函式內呼叫虛擬函式,並且在無法適當回報錯誤時,避免進行可能失敗的初始化。
定義
建構函式內可以執行任意的初始化動作。
優點
- 不需要擔心類別是否已經初始化過了。
- 已經經過建構函式充分初始化的物件可以作為
const
使用,而且與標準容器與演算法使用時更容易。
缺點
- 如果在建構函式內呼叫虛擬函式,這些呼叫不會被轉發至子類別的實作。 即使你的類別目前沒有子類別,未來的修改可能會悄然引入這個問題,造成困惑。
- 建構函式沒有簡單的方法來回報錯誤,除了直接讓程式崩潰 (這並不總是合適) 或使用例外 (也被我們 禁止 了)。
- 如果工作失敗了,那我們此時就會有個初始化失敗的物件。 這時可能需要提供
bool IsValid()
之類的方法來檢查狀態,但這種機制容易被遺漏,導致錯誤。 - 由於無法取得建構函式的函式指標,因此建構函式內的工作難以被移交,例如交給另一個執行緒。
決定
建構函式應該永遠不要呼叫虛擬函式。 在適當的情況下,終止程式可能是一種合理的錯誤處理方式。 否則,可以考慮像 TotW #42 所述那樣建立工廠方法 (Factory Method) 或者 Init()
方法。 避免在沒有其他狀態影響可呼叫公用方法的物件上使用 Init()
方法 (這類半建構狀態的物件特別難以正確使用) (譯註:這句話的意思是,如果沒有需要延遲初始化或者錯誤處理的需求,就不要特別為了初始化寫一個 Init()
,而是使用建構函式進行初始化即可。)