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

2021-06-13 16:17:10 字數 2613 閱讀 5748

chapter 4:設計與宣告

item18:讓介面容易被正確使用,不易被誤用

理想情況下應該是如果能編譯通過,那麼介面一定能實現你想要的,否則就不能編譯

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

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

struct day

int val;};

同樣的對month和year定義類似的結構體,這樣看起來貌似可以解決問題了。

ps:把day,month,year放在乙個完全封裝的資料中要比這樣單獨的定義乙個結構體要好,詳見item22.

date d(30, 3, 1995);                      // error! wrong types

date d(day(30), month(3), year(1995)); // error! wrong types

date d(month(3), day(30), year(1995)); // okay, types are correct

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

class month    // functions returning all valid

static month feb() // month values; see below for

... // why these are functions, not objects,因為非區域性的靜態變數的初始化順序沒法保證。 這樣保證用的時候變數都已經得到初始化了

static month dec()

... // other member functions

private:

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_ptrcreateinvestment();

但萬一客戶忘記了使用智慧型指標怎麼辦。這裡比較好的設計原則就是先發制人,令其直接返回乙個智慧型指標。這樣就幾乎完全消除了忘記釋放資源的可能性了。

5)又如item14中所言,tr1::shard_ptr允許繫結乙個資源釋放函式,但這有可能導致"企圖使用錯誤的資源析構函式"。比如說我們想使用的資源析構函式是getridofinvestment,而不是delete,為了避免錯誤,我們可以返回乙個將getridofinvestment繫結為刪除器的tr1::shared_ptr指標。這樣我們就試圖在createinvestment中建立乙個null的tr1::shared_ptr並以getridofinvestment作為刪除器。

像這樣:std::tr1::shared_ptrpinv(0, getridofinvestment);

但是這樣是不能編譯通過的,因為0是int型,不能轉化為指標,就算可以轉化,這樣也不好。這裡可以使用強制轉化來實現。這樣**就變成了:

std::tr1::shared_ptrcreateinvestment()

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。

Effective C 學習筆記

學習effective c 已經有相當長的一段時間了,今天抽出時間又堵了一遍第一部分 c語言 c 以c語言為基礎,幾乎支援所有的c語言成分,例如區塊 語句 預處理 內建資料型別 陣列 指標等,c語言的侷限是 沒有模板 沒有異常 沒有過載 物件導向的c 也就是加上了物件特性的c,類 封裝 繼承 多型 ...

Effective C 學習筆記

1 c 是乙個複合式的語言 c 中不同部分有著不同的語言特性,例如 1.1 在c中傳遞形參時,按照值傳遞比按照指標傳遞效率更高 1.2 在物件導向程式中,物件要按照const引用而不是按照值傳遞 1.3 在stl程式設計中採取按照值傳遞方式 所以說c 中沒有統一的準則,要按照不同的特性採取不同的使用...

effective c 學習筆記

如果不考慮應用程式的使用場合,僅僅考慮語言的靈活性,我贊成作者的想法。但是不同的應用它會有不同的效能要求,所以語言的選擇,應該是用 最適合 條款去選擇。使用巨集定義常量,若定義在標頭檔案中,則所有包含標頭檔案的都可以使用。巨集定義,在預處理的時候進行替換。巨集定義一些簡單的函式,可以減少呼叫開銷,但...