18. Make interfaces easy to use correctly and hard to use incorrrectly.
總結:
第一,好的接口很容易被正确使用,不容易被誤用。你應該在你的所有接口中努力達成這些性質。
第二,“促使正确使用”的辦法包括接口的一緻性,以及與内置類型的行為相容。
第三,“阻止誤用”的辦法包括建立新類型、限制類型上的操作,束縛對象值,以及消除客戶的資源管理責任。
第四,tr1::shared_ptr支援定制型删除器(custom deleter)。這可防範DLL問題,可被用來自動解除互斥鎖等等。
19.Treat class design as type design.
1)新type的對象應該如何被建立和銷毀?
2)對象的初始化和對象的指派有什麼樣的差别?
3)新type的對象如果被passed by value(以值傳遞),意味着什麼?
4)什麼是新type的“合法值”?
5)你的新type需要配合某個繼承圖系(inheritance graph)嗎?
6)你的新type需要什麼樣的轉換?
7)什麼樣的操作符和函數對此新type而言是合理的?
8)什麼樣的标準函數應該駁回?
9)誰該取用新type的成員?
10)什麼是新type的“未聲明接口”(undeclared interface)?
11)你的新type有多麼一般化?
12)你真的需要一個新type嗎?
Class的設計就是type的設計。在定義一個新type之前,請确定你已經考慮過本條款覆寫的所有讨論主題。
20.Prefer pass-by-reference-to-const to pass-by-value.
第一,盡量以pass-by-reference-to-const替換pass-by-value。前者通常比較高效,并可避免切割問題(slicing problem)。
第二,以上規則并不适用于内置類型,以及STL的疊代器和函數對象。對它們而言,pass-by-value往往比較适當。
21.Don't try to return a reference when you must return an object.
絕不要傳回pointer或reference指向一個local stack對象,或傳回reference指向一個heap-allocated對象,或傳回pointer或reference指向一個local static對象而有可能同時需要多個這樣的對象。條款4已經為“在單線程環境中合理傳回reference指向一個local static對象”提供了一份設計執行個體。
22.Declare data members private.
第一,切記将成員變量聲明為private。這可賦予客戶通路資料的一緻性、可細微劃分通路控制、允諾限制條件獲得保證,并提供class作者以充分的實作彈性。
第二,protected并不比public更具封裝性。
23.Prefer non-member non-friend functions to member functions.
甯可拿non-member non-friend函數替換member函數。這樣做可以增加封裝性、包裹彈性(packaging flexibility)和技能擴充性。
24.Declare non-member functions when type conversions should apply to all parameters.
如果你需要為某個函數的所有參數(包括被this指針所指的那個隐喻參數)進行類型轉換,那麼這個函數必須是個non-member.
25.Consider support for a non-throwing swap.
第一,當std::swap對你的類型效率不高時,提供一個swap成員函數,并确定這個函數不抛出異常。
第二,如果你提供一個member swap,也該提供一個non-member swap用來調用前者。對于classes(而非templates),也請特化std::swap。
第三,調用swap時應針對std::swap使用using聲明式,然後調用swap并且不帶任何“命名空間資格修飾”。
第四,為“使用者定義類型”進行std templates全特化是最好的,但是千萬不要嘗試在std内加入某些對std而言全新的東西。
感悟:這部分主要是介紹設計的時候需要注意的一些原則,總體來說都是在設計類的時候很容易遇見的問題。隻是最後一個條款,關于swap的内容,平時用的很少。需要在用到的時候,重新再仔細看下這部分的内容。