天天看點

c++101rule

組織政策

0,不拘于小結

縮進, 行的長度,命名,注釋,空格,制表,

1-4,高警告級别幹淨利落地進行編譯,使用建構系統,使用版本控制,代碼審查

風格

5,一個實體應該隻有一個緊湊的職責。 (依賴性管理,繼承,抽象,隐藏)

6,正确簡單清晰

7,

===================

01, 視c++為一個語言聯邦 

multiparadigm programming langauge, 支援過程(procedrual),面向對象object oriented, 函數形式functional

,泛型形式generic, 元程式設計metaprogramming

02, 盡量用const 取代enumu,inline替換#define

03, 盡量用const

const成員函數目的,為了該成員函數作用于const對象身上

兩個函數如果常量性不同,可以被重載

const對象大多數用于passed by poiner-to-const, passed by reference-to-const

bit constness,成員函數隻有在不更改任何non-static成員對象才可以說是const,也就是說不更改對象内任何一個bit.

logical constness,一個const成員函數可以修改它所處理的對象内的某些bits,但隻有用戶端偵測不出的情況下才得如此。

mutable 能夠釋放掉non-static 成員變量的bitwise constness限制。

const char & operator[](std::size_t position) const

{

    return text[position];

}

char & operator[](std::size_t position)

    return const_cast<char&>(static_cast<const TextBlock&>)(this)[position]);

第一次轉型static_cast<const TextBlock&>)(this)

第二次轉換const_cast<char&>

利用const實作non const版本

反向做法不可以。const成員函數承諾不改變其對象的邏輯狀态(logical state),non-const成員函數沒有這樣的承諾。

如果const調用non-const,就冒這樣的風險:你曾經承諾不改動的那個對象被改動了。

編譯器強制實施bitwise constness, 程式設計應該使用概念上的常量性(conceptual constness)

04, 确定對象使用前沒初始化

變量初始化規則,取決于變量類型和位置

1)内置類型變量初始化取決于變量定義的位置,函數體外定義的變量都初始化成0,函數體裡定義的内置類型不進行自動

初始化。

2)類類型變量的初始化,通過構造函數初始化(有預設/無預設需要顯示調用)

non-local-static 對象初始化順序無法确定

對應内置對象手工初始化

使用成員初始值清單,不要在構造函數裡面指派,免除“跨編譯單元之初始化次序”問題,用local static 對象替換

non-local static對象

05,了解c++預設編寫哪些函數

default構造函數,拷貝構造函數,拷貝指派

06,若不使用編譯器自動生成的函數,就該明确拒絕。

uncopable 将構造函數聲明為private

07,為多态聲明virtual 析構函數

08,别讓異常逃離析構函數

09, 絕不在構造函和析構過程中調用virtual函數

可以用private static函數,作為輔助函數給base calss構造函數傳值。

10, 另operator= 傳回一個reference to *this

連鎖指派。這隻是個協定,無強制性。内置标準類型和标準庫都提供

11,在Operator= 中處理自我指派

确定任何函數如果操作一個以上對象,其中多個對象是同一個對象時,執行仍然正确。

12, 複制對象時勿忘其每一個成分

1)複制local成員變量,2)base class内的coppying函數

copy assignment調用copy構造函數是不合理的。因為這就像試圖構造一個已經存在的對象。

copy構造函數調用copy assignment操作同樣無意義。 構造函數用來初始化新對象,而assginment

操作隻實施于已經初始化的對象上。對一個尚未構造好的對象指派,就像在一個尚未初始化的對象上

做“隻對已經初始化對象才有意義”的事情一樣。

如果你發現copy構造函數和copy assignment操作符有相近的代碼,消除重複代碼的做法是,

建立一個新的成員函數給兩者調用。這樣的函數往往是priviate,而且常命名init.

1)copy函數應該確定複制對象内的所有成員變量及base成分

2)不要嘗試以某個copying函數實作另一個copying函數。應該将共同機能放在第三個函數中,

并由copying函數共同調用。

資源管理

檔案描述符,互斥鎖,圖像界面字型筆刷,資料庫,socket

13, 以對象管理資源

獲得資源後立刻放進管理對象auto_ptr RAII resource acquisition is initialization

管理對象運用析構函數確定資源釋放

RCSP reference-couting smart pointer RCSP無法打破環狀引用。

tr1::shared_ptr就是RCSP

為了防止資源洩漏,請使用RAII對象,它們在構造函數中獲得資源并在析構函數中釋放資源

兩個常被使用的RAII classes分别是tr1_shared_ptr和auto_ptr

14, 在資源管理類中心小心copying行為

15,在資源類中提供對資源的通路

RAII class 應該提供取得其管理之資源的辦法

對原始資源的通路可能經由顯示轉換或隐士轉換,一般而言顯示轉換比較安全,隐士轉換對客戶比較

友善

16,對使用new和delete要采用相同的形式

delete pal; delete [] pal;

17,以獨立newed對象需要置入智能指針

以獨立語句将Newed對象置于智能指針内,如果不這樣,一旦異常抛出,有可能導緻難以覺察的資源洩漏

設計與聲明

18,讓接口容易被正确使用,不容易被誤用

理想上,如果客戶企圖使用某個接口卻沒有獲得他所預期的行為,這個代碼不應該通過編譯,反之則是

客戶想要的

接口一緻性。盡量與内置types一緻。

限制類型内什麼事可以做,什麼不可以做,常用const限制。

防止誤用,包括建立新類型,限制類型上的操作,束縛對象值,消除用戶端資源管理責任

tr1::shared_ptr支援定制删除器,可以防範DLL問題,可被用來自動解除互斥鎖。

19 設計class猶如設計type

重載函數,操作符,控制記憶體配置設定,定義對象初始化終結。

新type的對象應該如何被建立銷貨

對象的初始化和對象的指派應該有什麼樣的差别。這個答案決定構造函數和指派操作符的行為

新type對象如果被passed by value,意味着什麼? copy構造函數

什麼是typed的合法值。 class限制條件 invariants.

你新type需要配合某個繼續體系圖麼?

你的type需要什麼樣的轉換?

什麼樣的函數對新type而言合理,memeber函數

什麼樣的标準函數應該駁回, private函數

誰該取用新type成員。public成員

什麼是新type的未聲明接口

你的新type有多麼一般化 class template

你需要一個新type麼?

20,甯以pass-by-reference-to-const 替換pass-by-value

防止産生副本copy構造函數多次調用

防止對象切割,子類被視為基類對象傳遞

這個規則不适用于内置類型

21, 必須傳回對象時,别妄想傳回其reference.

絕不要傳回Pointer或reference指向一個local stack對象,或傳回reference指向

一個heap-allocated對象,傳回pointer或reference指向local static對象有可能

同時需要多個這樣的對象。

22,将成員變量聲明為private

23,甯以non-member ,non-friend替換member函數

資料以及操作資料的那些函數應該捆綁到一塊。

如果某些東西被封裝,它就不再可見。愈多東西被封裝,愈少人可以看到它。而遇少

人看到它,我們就有愈大的彈性去變化它。因為我們改變僅僅直接影響看到改變的那些

人和事物。是以,愈多東西被封裝,我們改變那些東西的能力就愈大。封裝使我們改變

事物隻影響有限客戶。

限制考慮對象資料,愈少代碼可以看到資料(也就是通路它),愈多的資料可以被封裝

,而我們也就遇能自由地改變對象資料,例如改變成員變量的數量,類型等等。如何測量

“有多少代碼可以看到一塊資料”,我們計算能通路該資料的函數,作為一種粗糙的測量。

愈多函數通路它,資料的封裝性愈低。

名字空間可以跨多個源檔案,類不能,類是一個整體不能分割。

prefer non-member non-friend to member,這樣做增加封裝性,包裹彈性,和機能擴充性。

24,若所有參數皆需類型轉換,請為此采用non-member函數

隻有參數被列入參數列,這個參數才是隐式類型轉換的合格參與者。

member的函數反面是non-member,而不是friend.

不能夠隻因為不該成為member,就自動讓它成為friend.朋友帶來的麻煩往往過于其價值。

25,考慮寫出一個不抛出異常的swap函數。

無法偏特化function template.隻能對class template偏特化。

可以重載function template

std::swap 典型實作

namespace std {

  template<typename T>

  void swap(T& a, T&b)

  {

    T temp(a);

    a = b;

    b = temp;

  }

如果不指派,隻想拷貝指針pimp.可以對std::swap特化,下面是基本構想,但目前無法通過編譯

namespace std{

  template<> void swap<Widget>(Widget &a, Widget& b)

    swap(a.pmpl, b.pmpl);

在Wiget類中加一個成員swap函數,這種做法同STL容器一緻。

class Widget {

  public:

    void swap(Widget & other)

    {

      using std::swap;

      swap(pImpl, other.pImpl);

    }

};

如果類Widget 和 WidgetImp是模闆

template<T>

class WidgetImp {...};

class Widget{...};無法在std内添加重載模闆,違反标準。

namespace WidgetStuf

  ...

  class Widget {...};

  void swap(widget<T> a, widget<T>b)

    a.swap(b);

如果打算置換兩個widget對象,根據c++名字查找法則 name lookups rules. argument-dependent lookup或koening lookup法則

pimp pointer to implementation.

本文轉自莫水千流部落格園部落格,原文連結:http://www.cnblogs.com/zhoug2020/p/6055074.html,如需轉載請自行聯系原作者

繼續閱讀