C++編程規(guī)范的個(gè)人總結(jié),非常實(shí)用
1禁止在頭文件中定義變量
2禁止在extern “C”中包含頭文件,否則會(huì)導(dǎo)致extern “C”嵌套,嵌套太多導(dǎo)致編譯錯(cuò)誤
3每個(gè)模塊提供多個(gè).c文件,在同一目錄下,目錄名為模塊名,并提供一個(gè).h文件
4.如果一個(gè)模塊包含多個(gè)模塊,則每個(gè)模塊提供一個(gè).h文件名為子模塊名
5.頭文件排版方式:1.按字母升序
??????????????????????????? ?2.將不穩(wěn)定(常修改)的放在前面
6.一個(gè)函數(shù)僅完成一項(xiàng)功能。重復(fù)代碼盡量寫(xiě)成函數(shù)
7.避免函數(shù)過(guò)程,最好不超過(guò)50行。
8.代碼嵌套不超過(guò)4層
9.函數(shù)不變參數(shù)要寫(xiě)為const
10.避免使用全局變量和靜態(tài)變量
11.函數(shù)參數(shù)個(gè)數(shù)不超過(guò)5個(gè)。檢查參數(shù)的有效性(是否為NULL)
12.命名規(guī)則
l???????? unix風(fēng)格:每個(gè)單詞小寫(xiě),并用下劃線分開(kāi)my_name
l???????? windows風(fēng)格:每個(gè)單詞首字母大寫(xiě) MyName
l???????? 文件命名采用小寫(xiě)字符
l???????? 全局變量g_??? 靜態(tài)變量s_
(5)宏:大寫(xiě)單詞_大寫(xiě)單詞
13:將宏定義的放在大括號(hào)內(nèi)
14:用const替代宏定義
15.inline函數(shù)的優(yōu)點(diǎn):
l???????? 編譯時(shí)不用展開(kāi),代碼Size小,
l???????? 可以加斷電,易于定位問(wèn)題。例如對(duì)于引用計(jì)數(shù)加減的時(shí)候
l???????? 編譯時(shí)編譯器做語(yǔ)法檢查
16.注釋在代碼上面(用空行隔開(kāi))或右邊
?
17
文件頭注釋:
/**
*@file?? ?????? 文件名
*@brief?? ???? 功能描述
*@version? ?版本
*@author?????? ?? ?作者
*@date ? ????創(chuàng)建日期
*/
?
函數(shù)頭注釋:
/**
*@descriotion
*@param a
*@param b
*@return c
*/
?
18程序塊采用縮進(jìn)風(fēng)格編寫(xiě),每級(jí)縮進(jìn)為4個(gè)空格。
19相對(duì)獨(dú)立的程序塊之間、變量說(shuō)明之后必須加空行
20.一條語(yǔ)句不能過(guò)長(zhǎng),拆分
l???????? 換行時(shí)要增加一級(jí)縮進(jìn)
l???????? 低優(yōu)先級(jí)操作符處劃分新行;換行時(shí)操作符應(yīng)該放下來(lái)放在新行首
l???????? 換行時(shí)一個(gè)完整的語(yǔ)句放在一行
l???????? 一行只寫(xiě)一條語(yǔ)句
21.兩個(gè)以上的關(guān)鍵字、變量、常量進(jìn)行對(duì)等操作時(shí),操作符前后應(yīng)該加空格
l???????? 符號(hào)、操作符后面加空格
l???????? if、for、while、switch后加空格。
l???????? !、~、++、--、&后不加空格
l???????? 注釋符與注釋內(nèi)容之間加空格
?
22一組相關(guān)的整數(shù)用enum
23.不相關(guān)的常量,即使取值相同,也必須分別定義
24變量使用時(shí)才聲明并初始化
25.避免構(gòu)造函數(shù)做復(fù)雜的初始化,
可以使用init函數(shù)():
l???????? 需要提供初始化返回信息
l???????? 數(shù)據(jù)成員初始化可能拋異常
l???????? 數(shù)據(jù)成員初始化失敗會(huì)造成該類對(duì)象初始化失敗,引起不確定狀態(tài)
l???????? 數(shù)據(jù)成員初始化依賴this指針:構(gòu)造函數(shù)沒(méi)結(jié)束,對(duì)象就沒(méi)有構(gòu)造出來(lái),構(gòu)造函數(shù)內(nèi)不能使用this成員
l???????? 數(shù)據(jù)初始化需要調(diào)用虛函數(shù)。在構(gòu)造函數(shù)和西溝函數(shù)中調(diào)用虛函數(shù),會(huì)導(dǎo)致未定義行為。
26初始化列表嚴(yán)格按照成員聲明順序初始化
27.使用c++風(fēng)格的類型轉(zhuǎn)換
const_cast 移除const屬性的轉(zhuǎn)換。避免使用
dynamic_cast下行轉(zhuǎn)換,基類指針轉(zhuǎn)換為子類指針。類型檢查,建議調(diào)試代碼中使用
static_cast 一般的強(qiáng)制轉(zhuǎn)換
reinterpret_cast 轉(zhuǎn)換不相關(guān)的類型,避免使用。
28.內(nèi)聯(lián)函數(shù)小于10行。且不要有循環(huán)、遞歸、虛函數(shù)。內(nèi)聯(lián)函數(shù)在頭文件中聲明
29.盡量用const引用取代指針。引用比指針安全,一定非空,一定不會(huì)指向其他目標(biāo)。不需要檢查非法NULL指針
30,一定要寫(xiě)構(gòu)造函數(shù)。
構(gòu)造函數(shù)參數(shù)列表的初始化
Message():
a(0),
b(“”),
c(NULL)
{
}
30.如果不定義構(gòu)造、拷貝、賦值、析構(gòu)等。編譯器會(huì)自動(dòng)生成。
默認(rèn)的構(gòu)造和賦值函數(shù)只是將元對(duì)象的成員簡(jiǎn)單賦值給目的對(duì)象,即淺拷貝(shallow copy)。使元對(duì)象和目的對(duì)象的成員指向同一內(nèi)存,導(dǎo)致資源重復(fù)釋放。自動(dòng)生產(chǎn)的析構(gòu)函數(shù)是空的,不能釋放已盛情的堆內(nèi)存。如果不需要拷貝夠咱函數(shù)和賦值函數(shù),將其聲明為private
31..讓operator=返回*this的引用,使之能連等。并檢查是否是自賦值
String&String::operator=(const String &rhs)
{
???? If(this!=&rhs)
{
???????? delete [] data;
???????? data=new char[strlen(rhs.data)+1];
???????? strcpy(data,rhs.data);
}
return *this;
}
?
32基類指針執(zhí)行刪除操作時(shí),基類的析構(gòu)函數(shù)設(shè)為共有虛擬的。保障派生類析構(gòu)函數(shù)被調(diào)用
33虛函數(shù)不使用默認(rèn)參數(shù),因?yàn)槭莿?dòng)態(tài)綁定的,而默認(rèn)參數(shù)是編譯時(shí)靜態(tài)綁定的,所以最終執(zhí)行的函數(shù)是一個(gè)定義在派生類,但卻使用了基類的默認(rèn)參數(shù)值的虛函數(shù)
?
class A
{
?
public:
?? virtual void display(const string& str="Base")
?? {
????? cout<<str<<endl;
?? }
};
class B:public A
{
public:
?? virtual void display(const string& str="Derived")
?? {
?? cout<<str<<endl;
?? }
};
?
A* a=new B();
a->display();//調(diào)用派生類display,調(diào)用基類默認(rèn)形參,輸出Base,
delete a;
a=NULL;
?
34.絕不重新定義(隱藏)繼承而來(lái)的非虛函數(shù)。因?yàn)闊o(wú)法動(dòng)態(tài)綁定
35.避免派生類中定義與基類同名但參數(shù)類型不同的函數(shù),引起虛函數(shù)調(diào)用失敗
36.派生類重定義的虛函數(shù)也要聲明virtual
37.僅在輸入?yún)?shù)類型不同個(gè),功能相同時(shí)重載函數(shù)
?
38建議4.7 使用重載以避免隱式類型轉(zhuǎn)換
說(shuō)明:隱式轉(zhuǎn)換常常創(chuàng)建臨時(shí)變量;如果提供類型精確匹配的重載函數(shù),不會(huì)導(dǎo)致轉(zhuǎn)換。
示例:
class String?
{
??? //…
??? String( const char* text );????? //允許隱式轉(zhuǎn)換
};
bool operator==( const String&, const String& );
//…代碼中某處…
if( someString == "Hello" ) {... }
上述例子中編譯器進(jìn)行隱式轉(zhuǎn)換,好像someString == String( "Hello")一樣,形成浪費(fèi),因?yàn)椴⒉恍?/p>
要拷貝字符。使用操作符重載即可消除這種隱式轉(zhuǎn)換:
bool operator==( const String& lhs, const String& rhs );???? //#1
bool operator==( const String& lhs, const char* rhs );?????? //#2
bool operator==( const char* lhs, const String& rhs );?????? //#3
?
39使用名字空間進(jìn)行歸類,避免符號(hào)沖突cout<<space_a::a+space_b::a;
40不要在頭文件中或者#include之前使用using指示符
?
41不要在extern "C"內(nèi)部使用#include包含其他頭文件
在C++代碼中調(diào)用C的庫(kù)文件,需要用extern "C"來(lái)告訴編譯器:這是一個(gè)用C寫(xiě)成的庫(kù)文件,用C的方式來(lái)鏈接它們。
嚴(yán)格的講,只應(yīng)該把函數(shù)、變量以及函數(shù)類型這三種對(duì)象放置于extern "C"的內(nèi)部。
如果把#include指令放在extern "C"里面,可能會(huì)導(dǎo)致extern "C"嵌套而帶來(lái)如下幾個(gè)風(fēng)險(xiǎn):
extern "C"嵌套過(guò)深,導(dǎo)致編譯錯(cuò)誤
extern "C"嵌套后,改變其他某些文件的編譯鏈接方式
?
42構(gòu)造函數(shù)初始化列表在同一行或按4格縮進(jìn)并排幾行
43類的聲明按照一定的次序和規(guī)范進(jìn)行。建議的次序如下:
?? 按照存取控制特性段排序:public、protected、private,如果沒(méi)有可以忽略。這個(gè)排序是讓聲
明的時(shí)候使用者首先看到最關(guān)心的特性(對(duì)外接口)。
?? 在每一段中按照如下順序聲明(先定義后續(xù)用到的類型,常量和enums;然后定義行為(構(gòu)造,析構(gòu),
成員函數(shù)),最后定義成員變量):
1.? typedefs和enums;
2. 常量;
3. 構(gòu)造函數(shù);
4. 析構(gòu)函數(shù);
5. 成員函數(shù),含靜態(tài)成員函數(shù);
6. 數(shù)據(jù)成員,含靜態(tài)數(shù)據(jù)成員。
?
44 使用‘//’注釋方式,而不是‘/* */',容易產(chǎn)生交叉錯(cuò)亂
?
45不直接使用C++的基本數(shù)據(jù)類型,不要假定其存儲(chǔ)尺寸長(zhǎng)度
說(shuō)明: C++標(biāo)準(zhǔn)沒(méi)有明確基本數(shù)據(jù)類型的大小與存儲(chǔ)格式,? 這些基本類型包括: short,? int, long, lo
long, float double等。這些基本數(shù)據(jù)類型在不同的編譯器中,實(shí)現(xiàn)有所不同,如:
long類型在32位編譯模式下為4字節(jié)長(zhǎng)度,在64位編譯模式下為8字節(jié)長(zhǎng)度。
所以建議不要直接使用基本數(shù)據(jù)類型。推薦如下兩種使用方式:
1、重定義基本數(shù)據(jù)類型
typedef int32_t int;
typedef int64_t long long;