歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Google C++ style guide——C++類

Google C++ style guide——C++類

日期:2017/3/1 9:38:48   编辑:Linux編程

1.構造函數的職責
構造函數中只進行那些沒有實際意義的初始化,因為成員變量的“有意義”的值大多不在構造函數中確定。
可以的話,使用Init()方法集中初始化為有意義的數據。
優點:排版方便,無需擔心類是否初始化。
缺點:
1)在構造函數中不易報告錯誤,不能使用異常;
2)操作失敗會造成對象初始化失敗,引起不確定狀態;
3)構造函數內調用虛函數,調用不會派發到子類實現中,即使當前沒有子類化實現,將來仍是隱患;
4)如果有人創建該類型的全局變量,構造函數將在main()之前被調用,有可能破壞構造函數中暗含的假設條件。
如果,對象需要有意義的初始化,考慮使用另外的Init()方法並(或)增加一個成員標記來指示對象是否已經初始化。

2.默認構造函數
當一個類有成員變量又沒有構造函數的時候,需要定義一個默認的構造函數,否則編譯器將會自動生成默認構造函數。
默認構造函數更適合於初始化對象,使對象內部狀態一致、有效。
編譯器生成的構造函數並不會對對象進行初始化。
如果你定義的類繼承現有類,而你又沒有增加信的成員變量,則不需要為新類定義默認構造函數。

3.明確的構造函數
對單參數構造函數使用C++關鍵字explicit。
通常,只有一個參數的構造函數可被用於轉換。
例如:定義了Foo::Foo(string name)跟void FooTest(Foo foo)
這個時候FooTest需要的是一個Foo對象作為參數,如果你傳入的是string類型的參數的話,構造函數Foo::Foo(string name)將被調用,
並且將該字符串轉換為一個Foo臨時對象傳給FooTest。
為避免構造函數被調用造成隱士轉換,可以將其聲明為explicit。
所有單參數構造函數必須是明確的。在類定義中,將關鍵字explicit夾到單參數構造函數前。
例外:在少數情況下,拷貝構造函數可以不聲明為explicit;特意作為其他類的透明包裝器的類。類似情況應在注釋中明確說明。

4.拷貝構造函數
僅在代碼中需要拷貝一個類對象的時候使用拷貝構造函數;不需要拷貝時應使用DISALLOW_COPY_AND_ASSIGN。
大量的類並不需要可拷貝,也不需要一個拷貝構造函數或賦值操作。
但如果你不主動聲明它們,編譯器會為你自動生成,而且是public的。
可以考慮在類的private中添加空的拷貝構造函數和賦值操作,只有聲明,沒有定義。
為了方便,可以使用宏DISALLOW_COPY_AND_ASSIGN。
//禁止使用拷貝構造函數和賦值操作的宏
//應在類的private:中使用
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&);//拷貝構造函數 \
void operator=(const TypeName&)//賦值操作函數


class Foo {
public:
Foo(int f);
~Foo();
private:
DISALLOW_COPY_AND_ASSIGN(Foo);
};

絕大多數情況下都應該使用DISALLOW_COPY_AND_ASSIGN,如果類確實需要可拷貝,應該在類的頭文件中說明原有,並適當定義拷貝構造函數和賦值操作。

5.結構體和類
僅當只有數據時使用struct,其他一概使用class。
如果與STL結合,對於仿函數和特性可以不用class而是使用struct。
注意:類和結構體的成員變量使用不同的命名規則。
類的成員變量以下劃線(_)結尾,結構體與普通變量一樣,都是小寫。

6.繼承
使用組合通常比使用繼承更適宜,如果使用繼承的話,只使用公共繼承。
C++實踐中,繼承主要用於兩種場合:實現繼承,子類繼承父類的實現代碼;接口繼承,子類僅繼承父類的方法名稱。
如果該類具有虛函數,其析構函數應該為虛函數。
限定僅在子類訪問的成員函數為protected,需要注意的是數據成員應始終為私有。

7.多重繼承
真正需要用到多重實現繼承的時候非常少,只有當最多一個基類中含有實現,其他基類都是以Interface為後綴的純借口類時才會使用多重繼承。
只有當所有超類除第一個外都是純接口時才能使用多重繼承,為確保它們是純接口,這些類必須以Interface為後綴。

8.接口
當一個類滿足以下要求時,稱之為純接口:
1)只有純虛函數和靜態函數(析構函數除外);
2)沒有非靜態數據成員;
3)沒有定義任何構造函數,如果有,也不含參數,並且為protected;
4)如果是子類,也只能繼承滿足上述條件以Interface為後綴的類。

9.操作符重載
除少數特定環境外,不要重載操作符。
一般不要重載操作符,尤其是賦值操作(opeartor =)比較陰險,應避免重載。
如果需要的話,可以定義類似Equals(),CopyFrom()等函數。

10.存取控制
將數據成員私有化,並提供相關存取函數。
如定義變量foo_以及取值函數foo()、賦值函數set_foo()。

11.聲明次序
在類中使用特定的聲明次序:public在private之前,成員函數在數據成員前。
定義次序如下:public、protected、private。
每一塊中,聲明次序一般如下:
1)typedefs和enums;
2)常量;
3)構造函數;
4)析構函數;
5)成員函數,含靜態成員函數;
6)數據成員,含靜態數據成員。
宏DISALLOW_COPY_AND_ASSIGN至於private塊之後,作為類的最後部分。

12.編寫短小函數
傾向於選擇短小、凝練的函數。
長函數有時是恰當的,因此對於函數長度並沒有嚴格限制。
如果函數超過40行,可以考慮在不影響程序結構的情況下將其分割一下。

C++ 設計新思維》 下載見 http://www.linuxidc.com/Linux/2014-07/104850.htm

C++ Primer Plus 第6版 中文版 清晰有書簽PDF+源代碼 http://www.linuxidc.com/Linux/2014-05/101227.htm

讀C++ Primer 之構造函數陷阱 http://www.linuxidc.com/Linux/2011-08/40176.htm

讀C++ Primer 之智能指針 http://www.linuxidc.com/Linux/2011-08/40177.htm

讀C++ Primer 之句柄類 http://www.linuxidc.com/Linux/2011-08/40175.htm

將C語言梳理一下,分布在以下10個章節中:

  1. Linux-C成長之路(一):Linux下C編程概要 http://www.linuxidc.com/Linux/2014-05/101242.htm
  2. Linux-C成長之路(二):基本數據類型 http://www.linuxidc.com/Linux/2014-05/101242p2.htm
  3. Linux-C成長之路(三):基本IO函數操作 http://www.linuxidc.com/Linux/2014-05/101242p3.htm
  4. Linux-C成長之路(四):運算符 http://www.linuxidc.com/Linux/2014-05/101242p4.htm
  5. Linux-C成長之路(五):控制流 http://www.linuxidc.com/Linux/2014-05/101242p5.htm
  6. Linux-C成長之路(六):函數要義 http://www.linuxidc.com/Linux/2014-05/101242p6.htm
  7. Linux-C成長之路(七):數組與指針 http://www.linuxidc.com/Linux/2014-05/101242p7.htm
  8. Linux-C成長之路(八):存儲類,動態內存 http://www.linuxidc.com/Linux/2014-05/101242p8.htm
  9. Linux-C成長之路(九):復合數據類型 http://www.linuxidc.com/Linux/2014-05/101242p9.htm
  10. Linux-C成長之路(十):其他高級議題

Copyright © Linux教程網 All Rights Reserved