1. 你需要重視類的設計
c++同其他面向對象程式設計語言一樣,定義了一個新的類就相當于定義了一個新的類型(type),是以作為一個c++開發人員,大量時間會被花費在擴張你的類型系統上面。這意味着你不僅僅是一個類的設計者同時是一個類型設計者。重載函數和運算符,控制記憶體配置設定和釋放,定義對象初始化和終結,這些都是你需要考慮的。是以你應該同語言設計者一樣,它們将時間浪費在内建類型的設計上,你就應該對類的設計施以同樣的關注。
2. 高效的類型的特征
設計好的類很具有挑戰性,因為設計好的類型具有挑戰性。好的類型有自然的文法,直覺的語義和一種或多種高效的實作。在c++中,沒有計劃好的類定義将不能達到上述任何目标。甚至一個類的成員函數的聲明方式都可能會影響到成員函數的性能。
3. 在設計一個類時,你需要問自己的若幹問題
是以你怎麼才能設計一個高效的類呢?首先,你必須了解你所面對的問題。幾乎每個類都需要你面對下面的問題,這些問題的答案常常會限制你的設計:
- 新類型的對象應該怎麼被建立和釋放?如何做将影響着類的構造函數和析構函數的設計,同樣影響記憶體配置設定和釋放函數(運算符new[],運算符 delete,和運算符delete[]看第8章)的設計。
- 對象初始化同對象指派怎麼不一樣?這個問題的回答決定了你的構造函數和指派運算符的行為,以及它們之間的差別。厘清楚初始化和指派很重要,因為他們對應着不同的函數調用(見 Item 4 )。
- 如果你的新類型對象被當作按值傳遞的參數會意味着什麼?記住,拷貝構造函數定義了一個類型的按值傳遞該如何實作。
- 你的新類型在值的合法性上是如何進行限制的?一般情況下,對于一個類的資料成員來說,隻有值的一些組合才是有效的。這些組合決定你的類必須維持不變性(invariants)。這些不變性就決定了你必須在你的成員函數内部做錯誤檢查,特别是在你的構造函數,指派運算符和”setter”函數中。這也同樣影響函數抛出的異常,以及函數的exception specifications(你可能很少使用)。
- 你的新類型需要配合某個繼承圖中麼?如果你的類從現存的類繼承而來,你就會受這些類設計的束縛,特别是受函數是virtual還是非virtual的束縛(Item 34和Item 36)。如果你希望别的類能繼承自你的類,就會影響你的聲明的函數應該是不是虛函數,特别是析構函數( Item 7 )
- 你的新類型允許何種類型轉換?你的類型會被淹沒在其他類型之中,那麼應該在你的類型和其他類型之間做轉換麼?如果你希望允許類型T1的對象隐式轉換成T2類型的對象,你要麼在類T1中寫一個類型轉換函數(例如,operator T2)要麼在類T2中寫一個non-explicit的單參數構造函數。如果你隻希望進行顯示轉換,就需要寫出執行轉換的函數,但是需要防止這種轉換調用類型轉換操作符或者non-explicit單參數構造函數。(隐式轉換和顯示轉換的例子,見 Item 15 )
- 對于新類型來說什麼樣的運算符和函數才是有意義的?你對這個問題的回答決定了你會為你的類聲明哪些函數。一些函數會是成員函數,但是另外一些不是(Item 23,Item 24,Item 46)。
- 什麼樣的标準函數應該被禁止?你應該将這樣的函數聲明成private( Item 6
- 誰對你的新類型的成員有通路權?這個問題幫助你決定哪些成員是public的,哪些是protected,哪些是private的。它同樣幫助你決定哪些類和函數應該是friend的,還有把一個類内嵌入另一個類是否有意義。
- 你的新類型的“未定義接口”是什麼?對于性能,異常安全(Item 29)和資源的使用(比如鎖和動态記憶體),你提供了什麼樣的保證?在這些領域中你所提供的保證将會對你的類實作強加限制。
- 你的新類型有多普遍?可能你沒有定義一個新的類型。你在定義一整個類型族。如果是這樣,你不需要定義一個新類,你需要的是一個新的類模版。
- 這個新類型真的是你想要的麼?如果定義一個新的派生類隻是為了在這個類中添加新的功能,那麼為了達到你的目标,簡單的定義一個或者多個非成員函數或者模闆會可能是較好的選擇。
這些問題很難回答,是以定義高效的類很具挑戰性。做好它吧,至少使得c++中自定義類産生的類型同内建類型一樣好,達到這麼目标,所有努力都值得。
作者:
HarlanC部落格位址:
http://www.cnblogs.com/harlanc/個人部落格:
http://www.harlancn.me/本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出,
原文連結如果覺的部落客寫的可以,收到您的贊會是很大的動力,如果您覺的不好,您可以投反對票,但麻煩您留言寫下問題在哪裡,這樣才能共同進步。謝謝!