程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++編碼規范

C++編碼規范

編輯:C++入門知識

C++編碼規范


命名規范

通用命名規則

類型名

類型名(類、結極體、類型定義(typedef)、枚舉)以大寫字母開始並混合大小寫,如

Line, SavingsAccount

變量名

變量名必須以小寫字母開始並混合大小寫, 如

line, savingsAccount

函數名

函數名必須以小寫字母的動詞開始並混合大小寫,如:

getName(), computeTotalWidth()

常量名

常量名(包括枚舉值)必須全部大寫並以下劃線分隔,如

MAX_ITERATIONS, COLOR_RED, PI

類的私有變量

類的私有變量必須以下劃線_作為後綴,如:

class SomeClass {

private:

int length_;

}

名字空間

名字空間的命名必須全部小寫,如:

model::analyzer, io::iomanager, common::math::geometry

接口類

接口類的命名以前綴的大寫I後跟類名, 如:

class IFoo

{

public:

virtual ~IFoo(){};

virtual void dooo() = 0;

}

模板類型名

模板類型命名必須是單個大寫字母,如:

template

template

縮略語

縮略語不必都是大寫,如:

exportHtmlSource(); // 這樣不好: exportHTMLSource();

openDvdPlayer(); // 這樣不好: openDVDPlayer();

全局變量

全局變量命名規則同變量名,只是全局變量必須總是以::來引用,如:

::mainWindow.open(), ::applicationContext.getName()

通用變量

通用變量(如函數參數)的命名應該就是它的類型,且首字母小寫,如:

void setTopic(Topic* topic) // 這樣不好: void setTopic(Topic* value)

// 這樣不好: void setTopic(Topic* aTopic)

// 這樣不好: void setTopic(Topic* t)

void connect(Database* database) // 這樣不好: void connect(Database* db)

// 這樣不好: void connect (Database* oracleDB)

文件名

文件名全部小寫,C++文件以.cpp結尾,頭文件以.h結尾,文件名與文件裡類的名字相同。

非通用命名規則

非通用變量(如局部變量)可以是這樣:

Point startingPoint, centerPoint;

Name loginName;

函數名中不應該再包括對象名,如:

line.getLength(); //這樣不好: line.getLineLength();

特殊命名規則

指針命名:

Line* line; // 這樣不好: Line* pLine;

// 這樣不好: Line* linePtr;

枚舉常量可以使用一個公共的類型名作為前綴,如:

enum Color {

COLOR_RED,

COLOR_GREEN,

COLOR_BLUE

};

bool類型的變量和函數返回值是bool的函數以is為前綴來命名,如:

isSet, isVisible, isFinished, isFound, isOpen

在某些情況下,有些比is前綴更適合(has, can, should),如:

bool hasLicense();

bool canEvaluate();

bool shouldSort();

當有屬性的情況下,使用get/set來存取,如:

employee.getName();

employee.setName(name);

matrix.getElement(2, 4);

matrix.setElement(2, 4, value);

想要計算什麼可以使用compute,如:

valueSet->computeAverage();

matrix->computeInverse()

想要想找什麼可以使用find, 如:

vertex.findNearestVertex();

matrix.findMinElement();

對象的初始化可以使用initialize ,而不要使用init

GUI組件的命名要把組件類型放到變量的後面,如:

mainWindow, propertiesDialog, widthScale, loginText,

leftScrollbar, mainForm, fileMenu, minLabel, exitButton, yesToggle 等。

復數形式變量命名使用如下:

vector points;

int values[];

變量具有前綴n表明這個變量代表了對象的個數,如:

nPoints, nLines

No為後綴的變量表明第幾個對象,如:

tableNo, employeeNo

迭代變量應該被命名為i, j, k等,如:

for (int i = 0; i < nTables); i++) {

:

}

for (vector::iterator i = list.begin(); i != list.end(); i++) {

Element element = *i;

}

對稱的命名:

get/set, add/remove, create/destroy, start/stop, insert/delete,

increment/decrement, old/new, begin/end, first/last, up/down, min/max,

next/previous, old/new, open/close, show/hide, suspend/resume, etc.

命名時避免使用縮略語

禁止否定的bool變量名,如:

bool isError; //這樣不好: isNoError

bool isFound; //這樣不好: isNotFound

異常類命名以Exception作為後綴,如:

class AccessException

{

:

}

注:

1) 不要使用匈牙利命名法

2) Windows定義了很多原有內建類型的同義詞(很反感,容易導致類型混亂),如DWORD、HANDLE等等,在調用Windows API時這是完全可以接受甚至鼓勵的,但在非調用API時盡量使用原來的C++類型,例如,使用const TCHAR *而不是LPCTSTR;原因:有助於代碼的移植。特別是服務器後台開發人員,盡量使用標准的C++類型。

代碼書寫規范

C++是個特性極其豐富而復雜的語言,本文檔旨在提供如何編寫高質量C++程序的建議。

原則

正確、簡單和清晰第一

軟件簡單為美(Keep it Sample Software, KISS原則),正確優於速度,簡單優於復雜,清晰優於機巧,安全優於不安全。

要避免出現代碼“壞味道”,摘錄自《重構 改善既有代碼的設計》

代碼的壞味道

1. 重復代碼

2. 過長函數

3. 過大類

4. 過長參數列

5. 發散式變化

6. 霰彈式修改

7. 依戀情結

8. 數據泥團

9. 基本型別偏執

10. switch驚悚現身

11. 平等繼承體系

12. 冗贅類

13. 誇誇其談未來性

14. 令人迷惑的暫時值域

15. 過度耦合的消息鏈

16. 中間轉手人

17. 狎昵關系

18. 異曲同工的類

19. 不完善的程序庫類

20. 純稚的數據類

21. 被拒絕的遺贈

22. 過多的注釋

具體內容請參考《重構 改善既有代碼的設計》, 在寫代碼的過程中,加紅的幾個是特別需要注意的

編譯設置

在高警告級別進行編譯,使用VC編譯器應將警告級別打到最高4級,並設置將警告作為錯誤

寧要編譯時和連接時錯誤,而不要運行時錯誤

項目設置include, lib路徑使用相對路徑,不要使用絕對路徑

debug編譯生成的是名稱後加d ,如(debug是xxxd.exe, release是xxx.exe)

頭文件

正確使用頭文件可令代碼在可讀性、文件大小和性能上大為改觀。

頭文件以.h作擴展名

#define保護

所有頭文件 都應該使用#define防止頭文件被多重包含(multiple inclusion),命名格式為:___H_

為保證唯一性,頭文件的命名應基於其所在項目源代碼樹的全路徑。例如,項目foo中的頭文件foo/src/bar/baz.h按如下方式保護:

#ifndef FOO_BAR_BAZ_H_

#define FOO_BAR_BAZ_H_

#endif // FOO_BAR_BAZ_H_

注:不要使用#pragma once來防止重復包含,因為該指令是vc特有的,它是一個編譯器指令,其它的編譯器不保證能支持它,而#ifndef是語言層面的, 只要是支持c++的編譯器, 都支持,跨平台,兼容性更好。

頭文件依賴

使用前置聲明(forward declarations)盡量減少.h文件中#include的數量,加快編譯速度。

內聯函數

叧有當函數叧有10行甚至更少時才會將其定義為內聯函數(inline function)。

注:濫用內聯將導致程序變慢。

函數參數順序

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

包含文件的名稱及次序

將包含次序標准化可增強可讀性、避免隱藏依賴(注:隱藏依賴主要是指包含的文件編譯)

頭文件包含次序如下:C庫、C++庫、其他庫的.h、項目內的.h。

實現文件(如dir/foo.cpp)包含次序如下:

dir2/foo2.h(優先位置,詳情如下)

C系統文件

C++系統文件

其他庫頭文件

本項目內頭文件

在包含文件裡不要使用.(當前目錄)和..(父目錄),如:

#include “../abc.h” // 不要這樣使用

作用域

命名空間

在.cpp文件中,允許甚至提倡使用未具名命名空間,以避免運行時的命名沖突: namespace {

// .cc 文件中 // 命名空間的內容無需縮進

enum { UNUSED, EOF, ERROR }; // 經常使用的符號

bool AtEof() { return pos_ == EOF; } // 使用本命名空間內的符號EOF

} // namespace

然而,不特定類關聯的文件作用域聲明在該類中被聲明為類型、靜態數據成員或靜態成員函數,而不是未具名命名空間的成員。像上文展示的那樣,不具名命名空間結束時用注釋// namespace標識。

不能在.h文件中使用未具名命名空間。

不要在頭文件中或者#include之前使用using namespace

局部變量

將局部變量盡可能置於最小作用域內,在聲明變量時就將其初始化。

全局變量

禁止class類型的全局變量

內建類型的全局變量是允許的,

當然多線程代碼中非常數全局變量也是被禁止的。

永遠不要使用函數返回值來初始化全局變量。

原因:c++標准在全局變量的構造函數、析構函數和初始化順序上沒有保證。因此每次生成都可能會有變化,從而導致難以覺察的BUGS。

對於全局的字符串常量,使用C風格的字符串,而不要使用STL的字符串:

const char kFrogSays[] = “ribbet”;

雖然允許在全局作用域中使用全局變量,使用時務必三思。大多數全局變量應該是類的靜態數據成員,或者當其叧在.cpp文件中使用時,將其定義到未具名命名空間中

注:靜態成員變量視作全局變量,所以,也不能是class類型!

如果一定要使用全局變量,請使用設計模式中的單件模式(singleton模式)。

C++類

用小類代替巨類

構造函數

類構造函數的初始化列表中成員變量初始化的順序應該與在h頭文件中聲明的順序一致。不要在構造函數體裡進行賦值操作。

對單參數構造函數使用C++關鍵字explicit。

虛擬函數

避免在構造函數和析構函數中調用虛擬函數

繼承

多用組合,少用繼承

接口

接口定義如下:

class IFoo

{

public:

virtual ~IFoo(){};

virtual void dooo() = 0;

};

即含有純虛函數,且實現虛析構函數的類。

接口類主要是為實現多態的。

操作符重載

盡量不要使用操作符重載

存取控制

將數據成員私有化,並提供相關存取函數

聲明次序

在類中使用特定的聲明次序:public:在private:之前,成員函數在數據成員(變量)前。

定義次序如下:public:、protected:、private:,如果那一塊沒有,直接忽略即可。

每一塊中,聲明次序一般如下:

1) typedefs和enums;

2) 常量;

3) 構造函數;

4) 析構函數;

5) 成員函數,含靜態成員函數;

6) 數據成員,含靜態數據成員。

編寫短小函數

函數體盡量短小、緊湊,功能單一

智能指針

如果確實需要使用智能指針的話,scoped_ptr完全可以勝任。在非常特殊的情況下,例如對STL容器中對象,你應該只使用std::tr1::shared_ptr,任何情況下都不要使用auto_ptr。

引用參數

引用傳遞的參數必須加上const,如果要將參數傳出,請使用指針。

缺省參數

禁止使用缺省函數參數。

異常

不要使用C++異常。

異常會導致程序控制流通過查看代碼無法確定:函數有可能在不確定的地方返回,從而導致代碼管理和調試困難。

異常的實用性可能會刺激開發人員在不恰當的時候拋出異常,戒者在不安全的地方從異常中恢復。

運行時類型識別RTTI

禁止使用RTTI, 單元測試程序除外。

類型轉換

使用C++風格的類型轉換, 不要使用C風格的類型轉換。

1) static_cast:和C風格轉換相似可做值的強制轉換,或指針的父類到子類的明確的向上轉換;

2) const_cast:移除const屬性;

3) reinterpret_cast:指針類型和整型或其他指針間不安全的相互轉換,僅在你對所做一切了然於心時使用;

4) dynamic_cast:除測試外不要使用,除單元測試外,如果你需要在運行時確定類型信息,說明設計有缺陷(參考RTTI)。

前置自增和自減

對簡單數值(非對象)來說,兩種都無所謂,對迭代器和模板類型來說,要使用前置自增(自減)。

const的使用

在任何可以使用的情況下都要使用const。

預處理宏

使用宏時要謹慎,盡量以內聯函數、枚舉和常量代替之,字符串化(##)除外;

0和NULL

整數用0,實數用0.0,挃針用NULL,字符(串)用’/0’;

sizeof(sizeof)

用sizeof(varname)代替sizeof(type);

Boost庫

只使用Boost中被認可的庫。

STL容器

默認時使用vector。否則,選擇其他合適的容器

用vector和string代替數組

使用vector(和string::c_str)與非C++API交換數據

在容器中只存儲值和智能指針

用push_back代替其他擴展序列的方式

算法和比較器的參數應多用函數對象少用函數

DLL

分配和釋放內存

要避免在不同的模塊中分配和釋放內存,例如,在DLL中分配的內存,必須仍由該DLL來負責釋放,而不要交給調用該DLL的程序來釋放。

全局變量

不要在DLL中使用全局變量,除非你明確能這樣使用。

線程

盡量減少共享數據

在多線程設計中,盡量要減少線程間共享的數據

使用SVN規范

提交代碼必須寫提交日志

提交代碼,代碼必須是debug和release都可編譯運行的

在修改代碼之前,首先update

注釋規范

本注釋以簡單為主,風格遵循doxygen格式,以便於借助doxygen工具可直接生成文檔。

注釋的確很重要,但最好的代碼本身就是文檔(自文檔),注釋是為別人(下一個需要理解你的代碼的人)而寫的,認真點吧,那下一個人可能就是你!

注釋風格

統一使用// 來注釋,即雙斜槓 + 空格

文件注釋

通常,.h文件要對所聲明的類的功能和用法作簡單說明,.cc文件包含了更多的實現細節或算法討論,如果你感覺這些實現細節或算法討論對於閱讀有幫助,可以把.cc中的注釋放到.h中,並在.cc中指出文檔在.h中。

不要單純在.h和.cc間復制注釋,復制的注釋偏離了實際意義。

// @brief 簡要描述

// @author 作者

類注釋

// 類描函數注釋

// 函數描述

// @param 參數 描述

// @return 返回值 描述

變量注釋

注釋占一行, 不要這樣:

Point centerPoint; // 中心點

應該這樣:

// 中心點

Point centerPoint;

C++命名規則

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved