第四章: 設計與宣告
18. 讓介面更容易被正確使用,不易被誤用
- 將你的class的public介面設計的符合class所扮演的角色,必要時不僅對傳參型別限制,還對傳參的值域進一步限制,
19. 設計class猶如設計type
- 內置型別如int、float等,本質也是一個class,用戶自定義的class的行為和狀態應當與內置型別類似的,設計class時,首先要考慮構造和析構、然后是賦值操作如何實作、考慮class是否要繼承某一已有class、盡量使你的class一般化等等需要考慮的問題,
20. 寧以pass-by-reference-to-const替代pass-by-value
- 這個準則很常見,使用const參考傳參以避免拷貝和修改入參,看具體場景,如果是需要修改入參,那么就不要加const、如果入參是簡單內置型別,拷貝不怎么消耗資源,那么直接傳值也是可以的,同樣,使用指標也是一樣的道理,此外,傳class的參考或指標也可以避免物件切個問題,例如函式接受一個父類物件,當傳入子類物件時,父類物件建構式會被呼叫,此時子類的屬性就會丟失,即切割問題,這是不希望的,
21. 必須回傳物件時,不要妄想回傳reference
- 很顯然的一點就是,你不能回傳一個locakl物件的指標或者參考,因為,函式呼叫結束后,所有存盤在堆疊上的local物件都將被銷毀,此外,可以回傳在函式內構造的堆物件的指標,但盡量不要回傳其參考,參考如果在回傳后沒有保護好而被覆寫,則造成記憶體泄漏,
22. 將成員變數宣告為private
- 這是一個封裝合理的class應當遵守的規則,成員變數宣告為private的話,可以通過public介面間接控制成員變數,并加以特殊限制,這樣做也有缺點,就是撰寫代碼無法直接修改成員變數,代碼量增加,如果只需要保存讀取資料,不做其他操作,那么宣告一個結構體是一個不錯的選擇,
我們一把不使用protected成員,沒什么用,
23. 寧以non-member、non-friend替換member函式
- 如果一個操作是一般性的,并不是class特有的,那么將其抽離class單獨宣告定義,
24. 若所有引數都需要型別轉換,請為此采用non-member函式
- 這里的所有引數包括this指標,所以連this指標都需要轉換型別,那么這個函式其實就不應該是這個class的成員函式,應當抽離class,
25. 考慮寫一個不拋出例外的swap函式
- 使用
std::swap吧,我覺得目前夠用了
第五章 實作
我們寫c++代碼,一個是如何設計架構,即定義class及其成員函式和成員資料,以及不同class之間的通訊關系;另一個是如何具體實作每個函式,對每個函式或成員函式的功能進行實作,這部分每個功能相對獨立,比較底層,但其中也有些需要注意的點,主要有以下幾個:
26. 盡可能延后變數定義式的出現時間
- 這樣可以提高程式的效率,但我并不認為會提高程式的可讀性,對于那些不是非常在意運行效率的函式,可讀可維護性要排在效率前面,如初始化,而那些會回圈呼叫很多次的代碼,如模型推理計算,效率至上,此外,編譯器也會盡可能優化代碼,以提高運行時效率,
27. 盡量少做轉型動作
C++中的cast方法有四種:
①const_cast:用于移除物件身上的const屬性,只此一個功能,常用,低風險,
②static_cast:用于強制隱式轉換,例如將int轉為double,將基類指標轉為子類指標時不進行安全檢查,不可用于移除const屬性,常用,低風險,
③dynamic_cast:用于執行類繼承體系中安全向下轉型,也就是用來決定某個物件是否歸屬類繼承體系中的某個型別,比如可以將多型基類(包含虛函式的基類)的指標強制轉換為派生類的指標,很耗時,不常用,高風險,
④reinterpret_cast:用于執行低級轉型,例如將int*轉為int,執行的是逐個位元復制的操作, 不用,高風險,
- 所以,首先盡量避免轉型,或者對于不可避免的轉型,將轉型操作隱藏到函式里面,并且盡量使用C++style的轉型方法,不要使用早期C風格的那種方法,在類繼承體系中進行上行轉換時,
dynamic_cast和static_cast效果一樣且安全,但下行轉換時,dynamic_cast會進行型別安全檢查且耗時,而static_cast不進行檢查,所以如果有必要且明確基類指標是哪個子類時,通常使用static_cast即可,
移除const屬性是危險的,如無十分必要請不要這樣做,肯定有其他方法規避這種危險操作,
28. 避免回傳handle指向物件的內部成分
- 即不要回傳指向物件資料成員的指標或參考,以保證物件的封裝性,防止外部改變物件內部資料,如果非要這樣做,請將回傳值加上const屬性,以禁止修改,
29. 為例外安全所做的努力是值得的
- 這條準則不好總結,大概來說就是對那些可能導致例外發生的函式進行例外捕獲并進行適當的處理,以避免記憶體泄漏,
30. 透徹了解inline的里里外外
- 直接定義在class體內的成員函式默認是行內的,也可以在class體外顯式宣告行內函式,但最終是否執行行內替換由編譯器決定,它只會將那些小型、頻繁呼叫的函式編譯為行內函式,這樣能盡可能降低代碼膨脹并提升程式執行速度,
31. 將檔案間的編譯依存關系降至最低
- 即讓代碼依賴宣告式而非定義式,這樣定義式發生改變不會導致依賴于該定義式的其他代碼也需要重新編譯,基于此構想的兩種方案是:
Handle class和interface class,這是在我們平時構建工程的時候經常遇到的兩種設計方法, - 程式庫頭檔案應該以“完全且僅有宣告式”的形式存在,其他代碼依賴此檔案即可,
小結:
以上即總結,明天上班,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/482826.html
標籤:其他
下一篇:Python復合陳述句
