天天看點

Google C++ style guide——頭檔案

1.#define保護

使用#define防止頭檔案被多重包含。命名格式為:<PROJECT>_<PATH>_<FILE>_H_

例如,foo中的頭檔案foo/src/bar/baz.h

#ifndef FOO_BAR_BAZ_H_

#define FOO_BAR_BAZ_H_

...

#endif //FOO_BAR_BAZ_H_

2.頭檔案依賴

使用前置聲明盡量減少.h檔案中#include的數量。

頭檔案被更改時,需要重新編譯。那些包含了該頭檔案的代碼也需要重新編譯,是以,我們應該實作盡可能少的在頭檔案中包含頭檔案。

前置聲明可以明顯的減少需要包含的頭檔案數量。假如你在一個頭檔案中需要用到類File,但不需要通路File的聲明,則頭檔案隻需前置聲明class File。

在以下情況可以使用類Foo而無需通路類的定義。

1)将資料成員類型聲明為Foo *或者Foo &;

2)參數、傳回值類型為Foo的函數隻是聲明(不在頭檔案内定義實作);

3)靜态資料成員的類型可以被聲明為Foo(因為靜态資料成員的定義在類定義之外)。

如果你的類是Foo的子類,或者含有類型為Foo的非靜态資料成員,則必須為之包含頭檔案。

有時,使用指針成員替代對象成員的确更有意義。但是,這樣的做法會降低代碼可讀性及執行效率。如果僅僅為了少包含頭檔案,還是不要替代比較好。

當然,.cc或者.cpp無論如何都需要所使用類的定義部分,自然也就會包含若幹頭檔案。

3.内聯函數

隻有當函數隻有10行甚至更少時才會将其定義為内聯函數。

當函數被聲明為内聯函數之後,編譯器可能會将其内聯展開,無需按通常的函數調用機制調用内聯函數。

優點:當函數體比較小的時候,内聯該函數可以令目标代碼更加高效。例如存取函數,以及其他一些比較短的關鍵執行函數。

缺點:濫用内聯将導緻程式變慢,内聯有可能使目标代碼量或增或建,這取決與被内聯的函數的大小。内聯較短小的存取函數通常會減少代碼量,但内聯一個很大的函數(如果編譯器允許的話),将顯著增加代碼量。

在現在處理器上,由于更好的利用指令緩存,小巧的代碼往往執行更快。

一個比較得當的處理規則是,不要内聯超過10行的函數。對于析構函數應慎重對待,析構函數往往比其表面看起來要長,因為有一些隐式成員和基類析構函數(如果有的話)被調用。

虛函數和遞歸函數即使被聲明為内聯的,也不一定就是内聯函數。通常,遞歸函數不應該被聲明為内聯的(遞歸調用堆棧的展開并不像循環那麼簡單,比如遞歸層數在編譯時可能是未知的,大多數編譯器都不支援内聯遞歸函數)。析構函數内聯的主要原因是其定義在類的定義中,為了友善抑或是對其行為給出文檔。

4.-inl.h檔案

複雜的内聯函數的定義,應放在字尾名為-inl.h的頭檔案中。

在頭檔案中給出内聯函數的定義,可令編譯器将其在調用出内聯展開。然後,實作代碼應完全放到.cc檔案中,我們不希望.h檔案中出現太多實作代碼,除非這樣做在可讀性和效率上有明顯優勢。

如果内聯函數的定義比較短小、邏輯比較簡單,其實作代碼可以放在.h檔案中。例如,存取函數的實作理所當然都放在類定義中。處于實作和調用的友善,較複雜的内聯函數也可以放到.h檔案中,如果你覺得這樣會使頭檔案顯得笨重,還可以将其分離到單獨的-inl.h中。這樣即把實作和類定義分離開來,當需要時包含實作所在的-inl.h即可。

同樣的,-inl.h也是需要#define保護的。

5.函數參數順序

定義函數事,參數順序為:輸入參數在前,輸出參數在後。

6.将包含次序标準化可增強可讀性、避免隐藏依賴,次序如下:C庫、C++庫、其他庫的.h、項目内的.h。

相同目錄下頭檔案按字母序是不錯的選擇。

繼續閱讀