Effective C++學習筆記之第四章(1)

來源:互聯網
上載者:User
chapter 4:設計與聲明

item18:讓介面容易被正確使用,不易被誤用
理想情況下應該是如果能編譯通過,那麼介面一定能實現你想要的,否則就不能編譯

假設正在設計一個表示時間資料的類的建構函式:Date(int month, int day, int year);這樣會出現兩個問題,一是傳參的順序不對,而是所傳參數的取值範圍不對。

1)使用者在傳參的時候順序不對。OK,也許你想到了用結構體,並且不允許隱式轉換。如下:

struct Day{explicit Day(int d):val(d){ }int val;};

同樣的對Month和Year定義類似的結構體,這樣看起來貌似可以解決問題了。
PS:把Day,Month,Year放在一個完全封裝的資料中要比這樣單獨的定義一個結構體要好,詳見item22.

Date d(30, 3, 1995);                      // error! wrong typesDate d(Day(30), Month(3), Year(1995));    // error! wrong typesDate d(Month(3), Day(30), Year(1995));    // okay, types are correct

2)使用者在傳參的時候資料範圍不對。怎樣才能讓一個變數合理的表示它應該有的取值範圍呢。比如說這裡只有12個Month。OK,可以這樣來定義:

class Month {public:  static Month Jan() { return Month(1); }   // functions returning all valid  static Month Feb() { return Month(2); }   // Month values; see below for  ...                                       // why these are functions, not objects,因為非局部的靜態變數的初始化順序沒法保證。 這樣保證用的時候變數都已經得到初始化了   static Month Dec() { return Month(12); }    ...                                       // other member functionsprivate:  explicit Month(int m);                    // prevent creation of new Month values ...                                       // month-specific data};

然後直接調用Date d(Month::Mar(), Day(30), Year(1995));就OK了。
3)盡量讓你設計的類型跟built-in types保持一致。避免無端與built-in types不相容,其實就是提供行為一致性的介面。
4)任何介面如果如果要求客戶必須記得做某些是,就是有著"不正確使用"的傾向,因為客戶可能會忘記做那件事。比如說item13中動態分配的時候,為了避免記憶體的泄露,我們將返回的指標交給一個只能指標來負責記憶體的釋放。
std::tr1::shared_ptr<Investment> createInvestment();
但萬一客戶忘記了使用智能指標怎麼辦。這裡比較好的設計原則就是先發制人,令其直接返回一個智能指標。這樣就幾乎完全消除了忘記釋放資源的可能性了。
5)又如item14中所言,tr1::shard_ptr允許綁定一個資源釋放函數,但這有可能導致"企圖使用錯誤的資源解構函式"。比如說我們想使用的資源解構函式是getRidOfInvestment,而不是delete,為了避免錯誤,我們可以返回一個將getRidOfInvestment綁定為刪除器的tr1::shared_ptr指標。這樣我們就試圖在CreateInvestment中建立一個null的tr1::shared_ptr並以getRidOfInvestment作為刪除器。
像這樣:std::tr1::shared_ptr<Investment> pInv(0, getRidOfInvestment);
但是這樣是不能編譯通過的,因為0是int型,不能轉化為指標,就算可以轉化,這樣也不好。這裡可以使用強制轉化來實現。這樣代碼就變成了:

std::tr1::shared_ptr<Investment> createInvestment(){std::tr1::shared_ptr<Investment> pInv(static_cast<Investment*>(0),getRidOfInvestment);pInv= ...;//指向一個正確的對象;return pInv;}

6)當然,如果被pInv管理的原始指標可以在建立pInv之前先確定下來,那麼"將原始指標傳給pInv建構函式"會比"先將pInv初始化為null再對它做一次賦值操作"要好,詳見item26.
7)另外一個tr1::shared_ptr的一個很好的性質是:它會自動使用它的"每個指標專屬的刪除器",因而消除另一個潛在客戶錯誤——"cross-DLL problem"。這個問題發生於"對象在一個動態連結程式庫DLL中被new建立,卻在另一個動態連結程式庫DLL中被delete銷毀".在許多平台上,這一類"跨DLL的new/delete的成對運用會導致runtime error。tr1::shared_ptr可以避免這個問題,因為它預設的刪除器是來自"tr1::shared_ptr被建立的那個DLL"的delete。也就是說被建立的那個tr1::shared_ptr可被傳遞給任何其他的DLLs,無需在意"cross-DLL problem".這個tr1::shared_ptrs會追蹤記錄,當資源的應用次數變成0時,調用綁定好的DLL's delete。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.