C++編碼規范


嚴謹編碼風格的重要性:

1.便於代碼合並,滿足團隊開發的需要

2.合格程序員的必備素質

3.防止編碼錯誤

4.易讀易理解

Google C++編碼規范(中文版)   

https://zh-google-styleguide.readthedocs.io/en/latest/google-cpp-styleguide/

1.頭文件盡可能多的使用前向聲明

好處:較少的文件依賴,減少編譯時間. 更加明確的類的依賴關系.

1 //.h中類B使用類A,使用前向聲明就不需要包含類A的頭文件,減少編譯工作量
2 class CA; //前向聲明一個類A
3 class CB
4 {
5 public:
6     CA* m_pA;//聲明類A的指針
7     CA* GetClassA(CA *pA, CA &a); //聲明使用類A作為形參或返回值類型的函數
8     //CA m_A; Error,不能定義類A的對象
9 };

2.函數的參數順序,輸入參數在前,輸出參數在后

輸入參數一般為傳值或者指針,引用,前面加const

輸出參數一般為非常量指針或者引用

好處:根據參數的位置明確參數的作用,一目了然

1 //輸入參數: nInput cInput szInput
2 //輸出參數: nOutPut
3 void Fun(const int nInput, const char cInput, const char* pStrInput, int &nOutPut);

3.頭文件的包含順序

stdafx.h預編譯頭文件

先包含當前源文件對應的頭文件

C系統頭文件

C++系統頭文件

其它庫頭文件

本項目其它頭文件

每個區域之間空一行

好處:增加可讀性

 1 #include "stdafx.h" //預編譯頭文件
 2 
 3 #include "test.h"   //當前源代碼對應的頭文件
 4 
 5 #include <stdio.h>  //C標准庫
 6 
 7 #include <iostream> //C++標准庫
 8 
 9 #include "library/read.h"   //其它庫頭文件
10 #include "library/write.h" 
11 
12 #include "one.h"  //當前項目下其它頭文件
13 #include "two.h"

 4.局部變量初始化,聲明變量后立即進行賦值初始化

 好處:避免未初始化產生的潛在錯誤

1     int nA = 0;
2     char szB = '\0';
3     float fC = 0.00f;
4     char szBuff[16] = {0}; //注意:初始化時指定的的元素個數比數組大小少,剩下的元素都回被初始化為0
5     StPeople tPeople = {0};

5.類的初始化

 1 class CStudent
 2 {
 3 public:
 4     CStudent():m_nAge(0),m_fScore(0.00f){}
 5     CStudent(int nAge, float fScore):m_nAge(nAge),m_fScore(fScore){};
 6 private:
 7     int m_nAge;
 8     float m_fScore;
 9 };
10 int _tmain(int argc, _TCHAR* argv[])
11 {
12     CStudent student; //使用無參的構造函數初始化 m_nAge=0 m_fScore=0.00f
13     CStudent studentTwo(20,99.5); //使用初始化例表構造函數初始化 m_nAge=20 m_fScore=99.5f
14 }

6.局部變量是個對象,應該避免多次調用構造與析構 

 1     //這里循環一千次,每次循環都得實例化對象,調用構造與析構
 2     for(int i = 0; i<1000; i++)
 3  { 4  CTest test; 5  test.Out(); 6  } 7 //下面同樣循環一千次,在外部實例化對象,只調用一次構造與析構 8  CTest testTwo; 9 for(int j = 0; j<1000; j++) 10  { 11  testTwo.Out(); 12 }

7.結構體和類使用, 只有當成員全部為數據時使用結構體,其它時一律使用類.

C++中結構體和類起到同樣作用,唯一區別是結構體默認成員和方法是public,而類默認是private

 

8.操作符重載,盡量不要用操作符重載,定義一個函數來處理顯得更加直觀

 1 class CPerson
 2 {
 3 public:
 4     CPerson(int nAge):m_nAge(nAge){}
 5     //重載==運算符
 6     bool operator==(const CPerson &ps)
 7     {
 8         if (this->m_nAge == ps.m_nAge)
 9         {
10             return true;
11         }
12         return false;
13     }
14     //使用Equal函數
15     bool Equal(const CPerson &ps)
16     {
17         return this->m_nAge == ps.m_nAge;
18     }
19 private:
20     int m_nAge;
21 };
22 int _tmain(int argc, _TCHAR* argv[])
23 {    
24     CPerson person1(20);
25     CPerson person2(20);
26     if(person1 == person2)
27     {
28         printf("person1 == person2\r\n");
29     }
30 
31     if(person1.Equal(person2))
32     {
33         printf("person1 == person2\r\n");
34     }
35 
36     getchar();
37 }

9.將類的數據成員私有化,提供Get Set方法進行訪問, 不使用對象,xxxx方式訪問

好處:提高代碼封裝性,有利於調試.

當數據成員出錯時,只需在Get Set方法下斷調試即可. 反之使用對象.xxx方式訪問,出錯時需要在所有調用處下斷,不利於調試.

 1 class CPerson
 2 {
 3 public:
 4     CPerson(int nAge):m_nAge(nAge){}
 5     int GetAge()
 6     {
 7         return this->m_nAge;
 8     }
 9     void SetAge(const int nAge)
10     {
11         this->m_nAge = nAge;
12     }
13 private:
14     int m_nAge;
15 };
16 int _tmain(int argc, _TCHAR* argv[])
17 {    
18     CPerson person1(20);
19     printf("age = %d\r\n",person1.GetAge());
20     person1.SetAge(30);
21     getchar();
22 }

10.類中的聲明順序, 先聲明public塊,再聲明protected塊,再聲明private塊,這三塊中聲明的順序一致

 1 class CPerson
 2 {
 3 public:
 4     //typedef
 5     typedef vector<int> VectorInt; 
 6     //常量
 7     const int m_kNum;
 8     //構造和析構函數
 9     CPerson(int nAge):m_kNum(100),m_nAge(nAge){}
10     ~CPerson(){}
11     //成員函數
12     int GetAge()
13     {
14         return this->m_nAge;
15     }
16     void SetAge(const int nAge)
17     {
18         this->m_nAge = nAge;
19     }
20     //數據成員
21 protected:
22     //聲明順序同上
23 private:
24     //聲明順序同上
25     int m_nAge;
26 };

11.編寫短小的函數,盡量不要超過40行

好處:方便提取重復代碼進行封裝,便於他人閱讀和修改,方便調試

 

12.不使用函數重載,直接使用函數名進行區分

好處:過多的函數重載種類會使調用者無從選擇

1 //函數重載
2 CPerson* GetPerson(const int nAge);
3 CPerson* GetPerson(const Sex emSex);
4 CPerson* GetPerson(const char* pStrName);
5 
6 //直接利用函數名進行區分
7 CPerson* GetPersonFromAge(const int nAge);
8 CPerson* GetPersonFromSex(const Sex emSex);
9 CPerson* GetPersonFromName(const char* pStrName);

13.函數參數禁止使用缺省參數

好處:避免他人調用函數時錯誤的理解

 

14.迭代器上使用前置自增自減(++i  --i)

好處:提高迭代器訪問的執行效率, 相比后置自增自減而言

 

15.當函數參數為對象時,盡量使用指針或者引用方式傳遞

//直接傳遞,需要構造一個新的對象,這個新的對象又得構造和析構,影響性能
void GetPeoson(const CPerson person);
//使用指針或引用方式傳遞實參,不需要構造新的對象
void GetPesSon(const CPerson *pPerson);
void GetPeoson(const CPerson &person);

 16.使用sizeof(變量名),而不是使用sizeof(數據類型)

好處:當修改變量的數據類型后,sizeof不需要同步更新成新的數據類型

 

17.格式要求

函數中返回值與函數名在同一行,如果參數過多需要進行換行並且對齊,每一行一個參數

1 void SetWindow(HWND hWnd,
2                int nWidth,
3                int nHeight,
4                int nX,
5                int nY,
6                DWORD dwStyle);

if和else if語句塊的括號需要另起一行,方便閱讀

1     if(aa > bb)
2     {
3         //......
4     }
5     else if(aa > cc)
6     {
7         //.....
8     }

適當添加空格,使代碼美觀更利於閱讀

1     int nA, nB, nC;
2     nC = nA + nB;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM