google code style ---2.頭文件

原文鏈接:https://google.github.io/styleguide/cppguide.html

第二章

  • 頭文件
    • 頭文件保護符【guard】
    • 前向聲明
    • 內聯函數
    • include 順序

2.0 前言


       通常,每一個.cc文件都應有相關的【associated】.h 文件。當然會有一些例外【exceptions】,例如單元測試和僅僅含有main函數的.cc文件。
       正確的使用頭文件將對代碼可讀性,文件大小,性能產生很大的影響【make a huge difference to】。
       下面的規則將會帶領你認識使用頭文件所遇到的陷阱【pitfall】。

2.1 self-contained 頭文件

2.2 頭文件保護符【guard】


       所有的頭文件都應含有#define保護,用來防止多重引入【multiple inclusion】,標識符的命名格式應爲

<PROJECT><PATH><FILE>_ H_

      爲了保證唯一性【uniqueness】,標識符的命名應根據項目源文件所在的全路徑。例如,文件/scr/bar/baz.h位於項目foo下,則該頭文件應有下面的頭文件保護符。

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

說明:第二種方法:#pragma once

2.3 前向聲明


避免使用前向聲明,取而代之的是使用#include引入需要的頭文件。

2.4 內聯函數

      當函數爲10行或者低於10行,可以定義該函數爲內聯函數。
定義:
      可以聲明函數爲內聯函數,從而允許編譯器通過內聯擴展,而不是像通常函數那樣進行調用。

優點:
      內聯函數可以生成更高效的目標代碼,只要被內聯的函數足夠的小巧。放心的去內聯accessors,mutators,以及其他小巧的重要的性能函數【通常爲set和get方法】。

缺點:
       過度【overuse】的使用內聯可能會導致程序變慢。根據函數大小的不同,內聯可能會導致代碼增加或者較少,內聯accessor函數通常將會減少代碼的大小,如果內聯一個很大的函數,將顯著【dramatically】增加代碼的大小。因爲更好的使用指令緩存【instruction cache】,現代的處理器在運行更少的代碼將會更快。

結論:
      經驗1:一個比較好【decent】的經驗是低於10行的函數可以將其內聯。特別注意析構函數,因爲隱式的成員和調用基類析構函數,所以析構函數實際上要比看起來要長。

      經驗2:通常【typically】不要內聯帶有loop或者是switch語句,除非大多數情況下,它們不會被執行【excuted】。
      雖然將一個函數定義爲內聯函數,但是這些函數通常不會被內聯。例如,虛函數和遞歸函數通常不會被內聯。通常遞歸函數不應該【should not】被內聯.最主要的原因將虛函數放到類的定義中,是爲了方便【convenience】或者爲了記錄他們的行爲,如accessors和mutators.

注:在使用虛函數內聯需要注意以下幾點:
      1.虛函數可以是內聯函數,內聯可以修飾虛函數的,但是當虛函數表現多態性的時候,不能進行內聯。
      2.inline virtual 唯一可以內聯的時候是:編譯器知道所調用的對象屬於哪個類,如Base::who(),這只有在編譯器具有實際對象而不是對象的指針或者引用的時纔會發生。
代碼示例

2.5 include順序


       按照如下的包含頭文件順序:相關的頭文件,C系統頭文件,C++標準庫頭文件,其他庫頭文件,該項目頭文件。

       所有的項目頭文件應按照項目的目錄樹進行排列,並且避免使用UNIX目錄別名,如(.當前目錄),(…父目錄)。例如:google-awesome-project/src/base/logging.h應該包含:

#include “base/logging.h”

       文件dir/foo.cc或者dir/foo_test.cc,兩者的目的是實現或者測試dir2/foo2.h中的函數,包含的頭文件應爲:

1.dir2/foo2.h
2.空行
3.C 系統頭文件(更確切的說,使用<>包含以.h結尾的文件)如:<unistd.h>,<stdlib.h>
4.空行
5.C++標準庫頭文件(不需要擴展名)如:<algorithm>,<cstddef>
6.空行
7.別的庫.h文件
8.自己本身庫.h文件

       使用空行將每一個非空的組分開。

       使用上述順序,如果相關的頭文件dir2/foo2.h遺漏【omits】任何必要的包含文件,則文件dir/foo.cc或者dir/foo_test.cc的build過程會崩潰【break】.因此這個規則保證了,如果build過程崩潰一定是目前的工作文件出現了問題,而不是別的包。

       dir/foo.cc和dir2/foo2.h通常在同一個目錄下(如,base/basictypes_test.cc和base/basictypes.h),但是通常也可能不在同一個目錄下。

       注意C頭文件(如,stddef.h)基本上【essentially】都是可以與C++系統頭文件(cstdef)交換的【interchangeable】。兩種風格都是可以接受的,但是更傾向於和當前的代碼庫相一致【consistency】.

       包含的頭文件中,每一組都應該按照字母表順序【alphabetically】進行排列,注意如果以往的代碼可能沒有遵循這個規則,如果在方便的時候可以將其修改。
       應該包含所有的依賴的頭文件,前向聲明除外(但是該特性不太建議使用),如果依賴bar.h中的標識【symbol】,如果還依賴於foo.h,不要因爲bar.h中已經依賴了foo.h就不去依賴他。除非foo.h明確的【explicitly】顯示bar.h提供相應的標識。
舉個栗子,google-awesome-project/src/foo.internal/fooserver.cc所包含的文件如下

#include “foo/server/fooserver.h”

#include <sys/types.h>
#include <unistd.h>

#include <string>
#include <vector>

#include “base/basictypes.h”
#include “base/commandlineflags.h”
#include “foo/server/bar.h”

例外:在特定系統【system-specific】的代碼中需要條件包含【conditional includes】,條件包含的代碼應該放在其他包含文件後面,當然特定平臺的代碼需要儘量的小巧,獨立。

#include “foo/public/fooserver.h”

#include “base/port.h”

#ifdef  LANG_CXX11
#include <initializer_list>
#endif  // LANG_CXX11
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章