1. 程式人生 > >Google C++程式設計規範

Google C++程式設計規範

1 標頭檔案

1.1 #define的保護

有標頭檔案都應該使用#define防止標頭檔案被多重包含( multiple inclusion) ,命名格式應當是:<PROJECT>_<PATH>_<FILE>_H_。為保證唯一性,標頭檔案的命名應基於其所在專案原始碼樹的全路徑。例如,專案foo中的標頭檔案foo/src/bar/baz.h按如下方式保護:

#ifndef FOO_BAR_BAZ_H_
#define FOO_BAR_BAZ_H_
...
#endif // FOO_BAR_BAZ_

1.2 行內函數

只有當函式只有10行甚至更少時才會將其定義為行內函數

1.3 函式引數順序

定義函式時,引數順序為:輸入引數在前,輸出引數在後

1.4 包含檔案的名稱和次序

次序如下: C庫、 C++庫、 其他庫的.h、 專案內的.h

2 建構函式

2.1 建構函式的職責

建構函式中只進行那些沒有實際意義的( 簡單初始化對於程式執行沒有實際的邏輯意義, 因為成員變數的“有意義”的值大多不在建構函式中確定)初始化, 可能的話,使用Init()方法集中初始化為有意義的資料。

2.2 明確的建構函式

對於單引數建構函式使用C++關鍵字explicit

2.3 結構體和類

僅當只有資料時使用struct,其它一概使用class

2.4 繼承

  • 所有的繼承必須是public
  • 資料成員應該始終為private
  • 含有虛擬函式的父類中,定義虛解構函式絕對必要
  • 當重定義派生的虛擬函式時, 在派生類中明確宣告其為virtual

2.5 介面

介面類即為抽象類,聲明瞭純虛擬函式,不能被直接例項化,其解構函式必須宣告為虛擬函式。一般以Interface為字尾命名。

2.6 操作符過載

除少數特定情況下,不要過載操作符

2.7 存取控制

  • 將資料私有化,並提供相關的存取函式
  • 存取函式的定義一般內聯的標頭檔案中

2.8 宣告次序

先public再protected最後private
每一塊中的宣告次序如下:

  • typedefs和enums;
  • 常量;
  • 建構函式;
  • 解構函式;
  • 成員函式,含靜態成員函式;
  • 資料成員,含靜態資料成員

3 其他C++特性

3.1 引用引數

按引用傳遞的引數必須加上const

3.2 預設引數

禁止使用預設函式引數

3.3 型別轉換

命名用static_cast<>()等C++的型別轉換, 不要使用 int y = (int)x或 int y = int(x)

  • static_cast: 和C風格轉換相似可做值的強制轉換, 或指標的父類到子類的明確的向上
    轉換;
  • const_cast:移除const屬性

3.4 前置自增和自減

迭代器和模板型別來說,要使用前置自增(自減),效率更高

3.5 const的使用

強烈建議在任何可以使用的情況下都要使用const

  • 如果函式不會修改傳入的引用或指標型別的引數,這樣的引數應該為const
  • 儘可能將函式宣告為const,訪問函式應該總是const,其他函式如果不會修改任何資料成員也應該是const,不要呼叫非const函式,不要返回對資料成員的非const指標或引用

3.6 整型

  • C++內建整型中, 唯一用到的是int, 如果程式中需要不同大小的變數, 可以使用<stdint.h>中的精確寬度( precise-width) 的整型,如int16_t
  • 使用斷言宣告變數為非負數,不要使用無符號型

3.7 預處理巨集

使用巨集時要謹慎,儘量以行內函數、列舉和常量代替之

3.8 0和NULL

整數用0,實數用0.0,指標用NULL,字元(串)用’\0’

3.9 sizeof

儘可能用sizeof(varname)代替sizeof(type)

4 命名約定

4.1 檔名命名

檔名要全部小寫,可以包含下劃線( _)或短線( -),按專案約定來

my_useful_class.cpp
my-useful-class.cpp
myusefulclass.cpp

對於包含大量內聯程式碼的類,可以有三個檔案

url_table.h //The class declaration
url_table.cpp // The class definition.
url_table-inl.h // Inline functions that include lots of code

4.2 型別命名

  • 型別命名每個單詞以大寫字母開頭不包含下劃線: MyExcitingClass、 MyExcitingEnum。
  • 所有型別命名——類、結構體、型別定義( typedef)、列舉——使用相同約定,例如:
// classes and structs
class UrlTable { ...
class UrlTableTester { ...
struct UrlTableProperties { ...
// typedefs
typedef hash_map<UrlTableProperties *, string> PropertiesMap;
// enums
enum UrlTableErrors { ...

4.3 變數命名

變數名一律小寫,單詞間以下劃線相連,類的成員變數以下劃線結尾,如my_exciting_local_variable、 my_exciting_member_variable_。

string table_name; // OK - uses underscore.
string tablename; // OK - all lowercase.
string tableName; // Bad - mixed cas

4.4 常量命名

在名稱前加k: kDaysInAWeek

4.5 函式命名

  • 普通函式:
    函式名以大寫字母開頭,每個單詞首字母大寫,沒有下劃線
    AddTableEntry()
    DeleteUrl()
  • 存取函式:
    存取函式要與存取的變數名匹配,這兒摘錄一個擁有例項變數num_entries_的類:
class MyClass {
public:
...
int num_entries() const { return num_entries_; }
void set_num_entries(int num_entries) { num_entries_ = num_entries; }
private:
int num_entries_;
};
  • 其他短小的行內函數名也可以使用小寫字母

4.6 名稱空間

名稱空間的名稱是全小寫的,其命名基於專案名稱和目錄結構: google_awesome_project

4.7 列舉命名

  • 列舉值應全部大寫,單詞間以下劃線相連: MY_EXCITING_ENUM_VALUE。
  • 列舉名稱屬於型別,因此大小寫混合: UrlTableErrors。
enum UrlTableErrors {
OK = 0,
ERROR_OUT_OF_MEMORY,
ERROR_MALFORMED_INPUT,
}