|
Posted on 2009-04-23 15:44 向往 閱讀(1095) 評論(4) 編輯 收藏 引用 所屬分類: C/C++/Script
接觸C++已經(jīng)有五個年頭了,多多少少在學(xué)習(xí)和工作的過程中有些感悟,遂一一記錄,勉己勉人. 有少許字段是摘抄自網(wǎng)上的文章,但存檔時只是隨手黏貼,丟失了作者信息,無法列出,對此表示歉意,并感謝發(fā)揚分享精神的原作者. 此外,若以后有新的感悟?qū)⒃诖颂砑?有不當之處,懇請指正.
- 指針賦值時,要謹防指針的同值性.如:
1 void SharePtr::operator = (Ptr *ptr) 2 { 3 if(mPtr != ptr) // 防止指針同值.其中mPtr是SharePtr類中用來保存指針的變
量. 4 { 5 if(mPtr != NULL) 6 { 7 delete mPtr;
// 如果不是同值, 刪除之前的指針. 8 mPtr = ptr; 9 } 10 } 11 }
- 不要忽視編譯警告,有些警告是出現(xiàn)bug并導(dǎo)致程序crash的征兆。比如類型轉(zhuǎn)化警告、數(shù)據(jù)未初始化警告都可能導(dǎo)致程序出錯。為了以后減少調(diào)試和避免錯誤的幾率,請重視編譯器的警告信息。
- 當工程需要給Class加導(dǎo)出前綴(如:__declspec(dllexport))卻有些沒有加時,其他工程引用它將會出現(xiàn)
Unrezosle Symbol的錯誤.
- 若某個類需要作為父類,其析構(gòu)函數(shù)必須聲明為virtual,否正子類的析構(gòu)函數(shù)無法調(diào)用,導(dǎo)致內(nèi)存泄漏.
- 新增一個Class時,先定好接口,然后再編碼.這樣可以不用經(jīng)常改動,減少編譯時間.
- 要謹防數(shù)值越界.對于有些存儲范圍小的變量,必須先進行越界處理,然后再賦值.如:
// 未添加數(shù)據(jù)越界檢測代碼 int num = -1; unsigned char ch = num; // ch的值不是-1,而是255.因為num超出了unsigned char表示的范
圍.
// 添加了數(shù)據(jù)越界檢測代碼 int num = -1; assert(num >=0 && num <= std::limit<unsinged char>::max()); // 若越界則彈出斷言 unsigned char ch = num;
- 在宏里邊盡量不定義變量,否則在外部調(diào)用兩次時,有可能出現(xiàn)變量重復(fù)定義的錯誤.
如果確實要定義變量,可以改寫成函數(shù).
- 不要為模式而模式.使用設(shè)計模式只是為了更好地復(fù)用和擴展,如果得到反作用,寧愿不用.
- 有些子類應(yīng)當覆蓋抽象類vitual成員時,千萬不能誤寫為重載.否則很難查出錯誤.
- 若有兩個人做同一個模塊時,需要商量好整體架構(gòu),明確分工,不可隨意修改他人的代碼,若要修改也應(yīng)告訴原作者.若對某些分工意見有分歧時,應(yīng)慢慢磨合,耐心心細比較,確定可行方案,切不可逃避,將問題延續(xù)下去.
- 定義接口時,盡量為使用者(用戶)提供明朗,統(tǒng)一,清晰的接口:
1)
盡可能使用默認參數(shù); 2) 使用管理器管理物體的創(chuàng)建刪除; 3)
使用抽象類抽象出若干類似Object的接口; 4) 函數(shù)名盡量使用動詞或動賓結(jié)構(gòu),并體現(xiàn)出職責; 5)
在實現(xiàn)相同功能的情況下,對外提供的函數(shù)應(yīng)盡可能少; 6)
能聲明成private或protected的數(shù)據(jù)成員和成員函數(shù)就不要聲明為public.
- 每個對象應(yīng)當完成并且只完成它該做的事,只管它該管的事,簡而言之,就是對象內(nèi)部,對象之間應(yīng)該保持"高內(nèi)聚,低耦合".
- 寫一個循環(huán)時,如果該循環(huán)體比較大,則應(yīng)該先寫好循環(huán)判斷條件,再實現(xiàn)細節(jié).
while(i > 0) { --i; } //實現(xiàn)如上代碼后,再寫實現(xiàn)細節(jié)(循環(huán)體).這樣做的目的是可以避免在實現(xiàn)細節(jié)后忘記增加--i等這類循環(huán)因子更新語句.
如:while(i > 0)
{ 循環(huán)
體; --i; }
- 代碼中的注釋應(yīng)當致力于解釋為什么,而不是怎么做。好的注釋并不是重復(fù)代碼中顯而易見的事實,而是引起對代碼中微妙的弱點的重
視。明白的代碼常常是被注釋所玷污了,不過對于作者顯而易見的東西對于讀者來說常常是晦澀的。一整段的注釋要比逐行解釋好的多。
- 類的組織Class organization
1).按照以下順序組織類的定義,按照用戶最為關(guān)心的順序組織類的代碼: Public type
forward-declarations & typedefs Public
constructors & destructor Public member
functions -----------------------------------------------------------
Protected type forward-declarations & typedefs
Protected member functions
-----------------------------------------------------------
Private type forward-declarations Private
member functions Private data members
2).盡量不要在類的定義體中進行函數(shù)定義。模板及內(nèi)聯(lián)函數(shù)除外。 3).復(fù)用public
private
protected關(guān)鍵字,將不同類型的成員分開,如成員函數(shù)和數(shù)據(jù)成員。 4).在繼承類里就不要重復(fù)寫virtual關(guān)鍵字,可以
將它們的聲明組織成一組。
- 在使用new/delete,
malloc/free時,注意"誰創(chuàng)建誰銷毀"的原則.除非有明確的規(guī)約,否則很容易造成內(nèi)存管理混亂,導(dǎo)致出現(xiàn)內(nèi)存錯誤.
- 頭文件包含其實是一想很煩瑣的工作,不但我們看著累,編譯器編譯的時候也很累,再加上頭文件中常常出現(xiàn)的宏定義。感覺各種宏定
義的展開是非常耗時間的,遠不如自定義函數(shù)來得速度。我僅就不同頭文件、源文件間的句則結(jié)構(gòu)問題提出兩點原則,僅供參考:
第一個原則
應(yīng)該是,如果可以不包含頭文件,那就不要包含了。這時候前置聲明可以解決問題。如果使用的僅僅是一個類的指針,沒有使用這個類的具體對象(非指針),也沒
有訪問到類的具體成員,那么前置聲明就可以了。因為指針這一數(shù)據(jù)類型的大小是特定的,編譯器可以獲知。 第二個原則應(yīng)該是,盡量在
CPP文件中包含頭文件,而非在頭文件中。假設(shè)類A的一個成員是是一個指向類B的指針,在類A的頭文件中使用了類B的前置聲明并便宜成功,那么在A的實現(xiàn)
中我們需要訪問B的具體成員,因此需要包含頭文件,那么我們應(yīng)該在類A的實現(xiàn)部分(CPP文件)包含類B的頭文件而非聲明部分(H文件)。
- 解決頭文件相互包含問題的方法之一:在.h文件里用class
A聲明,數(shù)據(jù)成員用指針或者引用,在.cpp里用#include"A.h"即可.
- 在索引列表時,最好能根據(jù)索引和名字來獲取元素,以滿足不同場合的需求.在編輯器制作中更彰顯其意義.
- 在類A的構(gòu)造函數(shù)里如果有類B成員變量b,并調(diào)用了b的某個函數(shù)如b.fun(),則b.fun()里邊不能調(diào)用A的指針.因
為此時A的指針尚未完成空間分配,強行調(diào)用將導(dǎo)致出錯.
這種情況在Debug下偶爾出錯,但在Release版下一定出錯.應(yīng)當引起
重視!
- 以二進制存儲信息時,要注意int等類型在不同的平臺不同CPU架構(gòu)下長度是不一樣的,故在寫入文件時,建議先用宏
(如#define INT_LENGTH
4)來表示寫進文件的長度.此外,還要注意字節(jié)序(高位在前還是低位在前)的問題.
所以一般情況下,用文本文件來存儲相關(guān)信息,避免
了那些問題.
- 由于std::vector里邊的內(nèi)存管理機制會適時釋放內(nèi)存以調(diào)整合適的大小,故在外部不要保存std::vector里的
元素地址.如果確實要保存,則每次增刪vector元素時必須更新外部的指針,否則將可能造成垃圾指針而出現(xiàn)內(nèi)存錯誤(有時候甚至不報錯,程序運行出現(xiàn)不
可預(yù)料的結(jié)果.很詭異,很難發(fā)現(xiàn)bug).
- 永遠不要在類的構(gòu)造或者析構(gòu)過程中調(diào)用虛函數(shù),因為這樣的調(diào)用永遠不會沿類繼承樹往下傳遞到子類中去。否則很有可能出現(xiàn)很隱晦
的bug.參見:http://www.enet.com.cn/article/2005/0706/A20050706431501_2.shtml
- 給有虛函數(shù)的模板類添加父類.即將公用接口抽象在父類里,就可以統(tǒng)一處理模板類了.
Feedback
@Sunshine Alike @sisco 如果本文對大家有所幫助,是我寫文章的初衷和動力.謝謝賞閱.
|