版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)
文檔簡介
C++Google大部分開源項目的主要編程語言.C++程序員都知道的,C++有很多強大的特性,bug,難以閱讀和維本段內(nèi)容的目的是通過詳細闡述C++注意事項來駕馭其復(fù)雜性.這些規(guī)則在保證代碼易于管理的同時,C++的語言特性風(fēng)格,亦被稱作可讀性,C++編程的約定.使用術(shù)語“風(fēng)格”有些用詞不當(dāng),因為這些習(xí)慣遠不止源代碼文件格式化這么簡單.使代碼易于管理的方法之一是加強代碼一致性.讓任何程序員都可以快速讀懂你的代碼這.標(biāo)識符的含義.創(chuàng)建通用,必需的習(xí)慣用語和模式可以使代碼更容易理解.在一些情況下可能有充分的理由改變某些編程風(fēng)格,但我們還是應(yīng)該遵循一致性原則,盡量不這么做.C++特性的臃腫C++是一門包含大量高級特性的龐大語言.某些情況下我們會限制甚至禁止使用某些特性.這么做是為了保持代碼清爽,避免這些特性可能導(dǎo)致的各種問題.指南中列舉了這類特性,并解釋為什么這些特性被限制使用.Google主導(dǎo)的開源項目均符合本指南的規(guī)定注意:C++教程,C++非常熟悉通常每一個.cc文件都有一個對應(yīng)的.h文件.也有一些常見例外,如單元測試代碼和只main().cc文件.正確使用頭文件可令代碼在可讀性、文件大小和性能上大為改觀.Self-contained所有頭文件要能夠自給自足。換言之,用戶和重構(gòu)工具不需要為特別場合而包含額外一個頭文件要有dne也不要求定義任何特別ybo.不過有一個例外,即一個文件并不是e-oand(platform-specific).inc.h文件聲明.cc-inl.h私有成員,那么它就只能定義在實例化該模板的.cc文件里。#define所有頭文件都應(yīng)該使用#define來防止頭文件被多重包含,命名格式當(dāng)是為保證唯一性,頭文件的命名應(yīng)該基于所在項目源代碼樹的全路徑.例如,項目foo/src/bar/baz.h可按如下方式保護優(yōu)點:能夠節(jié)省編譯時間,多余的#include會迫使編譯器展開更多的文件,處理更多的輸入。能夠節(jié)省不必要的重新編譯的時間。#include使代碼因為頭文件API.前置聲明來自命名空間std::的symbol時,其行為未定義。#include。極端情況下,前置聲明代替includes甚至都會暗暗地改變代碼的含義:#includeBD的前置聲明替代,test()f(void*symbolinclude冗長。.函數(shù):總是使用#include.#include定義:當(dāng)函數(shù)被聲明為內(nèi)聯(lián)函數(shù)之后,編譯器會將其內(nèi)聯(lián)展開,而不是按通常的函數(shù)調(diào)優(yōu)點:只要內(nèi)聯(lián)的函數(shù)體較小,內(nèi)聯(lián)該函數(shù)可以令目標(biāo)代碼更加高效.對于存取函數(shù)以及其它函數(shù)體比較短,性能關(guān)鍵的函數(shù),鼓勵使用內(nèi)聯(lián).缺點:濫用內(nèi)聯(lián)將導(dǎo)致程序變得更慢.內(nèi)聯(lián)可能使目標(biāo)代碼量或增或減,這取決于內(nèi)聯(lián)內(nèi)聯(lián)非常短小的存取函數(shù)通常會減少代碼大小,但內(nèi)聯(lián)一個相當(dāng)大的函數(shù)將戲劇性的增加代碼大小.現(xiàn)代處理器由于更好的利用了指令緩存,小巧的代碼往結(jié)論:一個較為合理的經(jīng)驗準(zhǔn)則是,不要內(nèi)聯(lián)超過10行的函數(shù).謹(jǐn)慎對待析構(gòu)函數(shù),析構(gòu)函數(shù)往往比其表面看起來要更長,因為有隱含的成員和基類析構(gòu)函數(shù)被調(diào)另一個實用的經(jīng)驗準(zhǔn)則:內(nèi)聯(lián)那些包含循環(huán)或switch語句的函數(shù)常常是得不償失(除非在大多數(shù)情況下,這些循環(huán)或switch語句從不被執(zhí)行)有些函數(shù)即使聲明為內(nèi)聯(lián)的也不一定會被編譯器內(nèi)聯(lián),這點很重要;不會被正常內(nèi)聯(lián).通常,遞歸函數(shù)不應(yīng)該聲明成內(nèi)聯(lián)函數(shù).YuleFox注:堆棧的展開并不像循環(huán)那么簡單,比如遞歸層數(shù)在編譯時可能是未知的,大多數(shù)編譯器都不支持內(nèi)聯(lián)遞歸函數(shù)).虛函數(shù)內(nèi)聯(lián)的主要原因則是想把它的函數(shù)體放在類定義內(nèi),為了圖個方便,抑或是當(dāng)作文檔描述其行為,#include使用標(biāo)準(zhǔn)的頭文件包含順序可增強可讀性,避免隱藏依賴:相關(guān)頭文件,C庫,C++庫,其他庫的.h,本項目內(nèi)的.h項目內(nèi)頭文件應(yīng)按照項目源代碼目錄樹結(jié)構(gòu)排列,避免使用UNIX特殊的快捷目錄.(當(dāng)前目錄)或..(上級目錄).例如,google-awesome-project/src/base/logging.h應(yīng)該按又如,dir/foo.cc或dir/foo_test.cc的主要作用是實現(xiàn)或測試dir2/foo2.h的功能,foo.cc中包含dir2/foo2.h優(yōu)先位置,詳情如下CC++.h.h這種優(yōu)先的順序排序保證當(dāng)dir2/foo2.h遺漏某些必要的庫時,dir/foo.cc或dir/foo_test.cc的構(gòu)建會立刻中止。因此這一條規(guī)則保證維護這些文件的人們首先看到dir/foo.ccdir2/foo2.h通常位于同一目錄下(base/basictypes_unittest.ccbase/basictypes.h),但也可以放在不同目錄下。不符合這條規(guī)則,要在方便的時候改正它們。您所依賴的符號(symbols)被哪些頭文件所定義,您就應(yīng)該包含(include)哪些頭文(forwarddeclarations)bar.h中的某個符號,哪怕您所包含的foo.hbar.h,bar.h,除非foo.h有明確說明它bar.hsymbolcc文件所對應(yīng)的「相關(guān)頭文件」已ccfoo.ccfoo.h就夠了,鼓勵在.cc文件內(nèi)使用匿名命名空間或static聲明.使用具名的命名空間時,其名稱可基于項目名或相對路徑.禁止使用using指示(using-directive)定義:命名空間將全局作用域細分為獨立的,具名的作用域,可有效防止全局作用域的:用域內(nèi)),命名空間在這基礎(chǔ)上又封裝了一層。舉例來說,兩個不同項目的全局作用域都有一個類Foo,這樣在編譯或運行時造成沖突.如果每個項目將代碼置于不同命名空間中project1::Fooproject2::Foo作為不同符號自然不會沖突。內(nèi)X::Y::foo()X::foo()ABI兼缺點:命名空間具有迷惑性,因為它們使得區(qū)分兩個相同命名所指代的定義更加困難。的限制。內(nèi)聯(lián)命名空間只在大型版本控制里有用。 用命名空間把文件包含,gflags的聲明/定義,以及類的前置聲明以外的整個源文件封裝起來,以區(qū)別于其它命名空間:不要在命名空間std內(nèi)聲明任何東西,包括標(biāo)準(zhǔn)庫的類前置聲明在std命名空間聲明實體是未定義的行為,會導(dǎo)致如不可移植.聲明標(biāo)準(zhǔn)庫下的實體,需要包含對應(yīng)的頭文件using何在頭文件中引入的命名空間都會成為公開API的一部分。static.cc但是不要在.hnamespace:使用靜態(tài)成員函數(shù)或命名空間內(nèi)的非成員函數(shù),盡量不要用裸的全局函數(shù).將一系列函數(shù)優(yōu)點:某些情況下,非成員函數(shù)和靜態(tài)成員函數(shù)是非常有用的,將非成員函數(shù)放在命名缺點:將非成員函數(shù)和靜態(tài)成員函數(shù)作為新類的成員或許更有意義,當(dāng)它們需要訪問外結(jié)論:有時,把函數(shù)的定義同類的實例脫鉤是有益的,甚至是必要的.這樣的函數(shù)可以被定義成靜態(tài)成員,或是非成員函數(shù).非成員函數(shù)不應(yīng)依賴于外部變量,應(yīng)盡量置于某個命名空間內(nèi).相比單純?yōu)榱朔庋b若干不共享任何靜態(tài)數(shù)據(jù)的靜態(tài)成員函數(shù)而創(chuàng)建類,不如使用命名空間。C+一次使用越近越好.這使得代碼瀏覽者更容易定位變量聲明的位置,了解變量的
bugconstexpr(PODPlainOldData)intcharfloat,以及POD類型的指針、數(shù)組和結(jié)構(gòu)體。經(jīng)過構(gòu)造函數(shù)完全初始化后的對象可以為const類型,也能更方便地被標(biāo)準(zhǔn)容實現(xiàn).即使當(dāng)前沒有子類化實現(xiàn),將來仍是隱患.在沒有使程序崩潰(因為并不是一個始終合適的方法)或者使用異常(因為已經(jīng)如果執(zhí)行失敗,會得到一個初始化失敗的對象,這個對象有可能進入不正常的狀態(tài),必須使用boolIsValid(構(gòu)造函數(shù)的地址是無法被取得的,因此,舉例來說,由構(gòu)造函數(shù)完成的工作是無法錯誤的方式.否則,考慮用Init()方法或工廠函數(shù).構(gòu)造函數(shù)不得調(diào)用虛函數(shù),或嘗試報告一個非致命錯誤.如果對象需要進行有意義的(non-trivial)初始化,考慮使用明確的Init()方法或使用工廠模式.AvoidInit()methodsonobjectswithnootherstatesthataffectwhichpublicmethodsmaybecalled(此explicit定義:隱式類型轉(zhuǎn)換允許一個某種類型(稱作源類型)的對象被用于需要另一種類型(稱作目的類型)的位置,intdouble除了語言所定義的隱式類型轉(zhuǎn)換,用戶還可以通過在類定義中添加合適的成員定轉(zhuǎn)換運算符實現(xiàn)(例如operatorbool()).在目的類型中定義隱式類型轉(zhuǎn)換,則通過以源類型作為其唯一參數(shù)(或唯一無默認(rèn)值的參數(shù))的構(gòu)造函數(shù)實現(xiàn).ExplicitC++11引入)類型轉(zhuǎn)換運算符,以保證只有當(dāng)目的類型在調(diào)用點被顯式寫明時才能進行類型轉(zhuǎn)換,例如使用cast.這不僅作用于隱式類型轉(zhuǎn)換,還能作用于C++11的列表初始化語法:這一代碼從技術(shù)上說并非隱式類型轉(zhuǎn)換,但是語言標(biāo)準(zhǔn)認(rèn)為這是explicit應(yīng)當(dāng)至用戶根本沒有意識到發(fā)生了類型轉(zhuǎn)換.隱式類型轉(zhuǎn)換會讓代碼難以閱讀,尤其是在有函數(shù)重載的時候,因為這時很難判如果單參數(shù)構(gòu)造函數(shù)沒有加上explicit關(guān)鍵字,讀者無法判斷這一函數(shù)究竟是explicit標(biāo)記.并沒有明確的方法用來判斷哪個類應(yīng)該提供類型轉(zhuǎn)換,這會使得代碼變得含糊不清.如果目的類型是隱式指定的,那么列表初始化會出現(xiàn)和隱式類型轉(zhuǎn)換一樣的問題,結(jié)論:在類型定義中,類型轉(zhuǎn)換運算符和單參數(shù)構(gòu)造函數(shù)都應(yīng)當(dāng)用explicit進行標(biāo)記.一個例外是,拷貝和移動構(gòu)造函數(shù)不應(yīng)當(dāng)被標(biāo)記為explicit,因為它們并不執(zhí)行類型轉(zhuǎn)換.對于設(shè)計目的就是用于對其他類型進行透明包裝的類來說,隱式explicitstd::initializer_listexplicitMyTypem={1,2};).總述:如果你的類型需要,就讓它們支持拷貝/移動.否則,就把隱式產(chǎn)生的拷貝和移定義:可拷貝類型允許對象在初始化時得到來自相同類型的另一對象的值,或在賦值時拷貝操作一般通過拷貝構(gòu)造函數(shù)與拷貝賦值操作符定義.string類型就是一個賦予相同類型的臨時對象的值(因此所有可拷貝對象也是可移動的).std::unique_ptr<int>就是一個可移動但不可復(fù)制的對象的例子.對于用戶定義的類型,移動操作一般是通過移動構(gòu)造函數(shù)和移動賦值操作符實現(xiàn)的.拷貝/移動構(gòu)造函數(shù)在某些情況下會被編譯器隱式調(diào)用.例如,通過傳值的方式傳優(yōu)點:可移動及可拷貝類型的對象可以通過傳值的方式進行傳遞或者返回,這使得API更簡單,更安全也更通用.與傳指針和引用不同,這樣的傳遞不會造成所有權(quán),了客戶端與實現(xiàn)在非作用域內(nèi)的交互,使得它們更容易被理解與維護這樣的對象API拷貝/移動構(gòu)造函數(shù)與賦值操作一般來說要比它們的各種替代方案,比如CloneCopyFromorSwap(),更容易定義,因為它們能通過編譯器產(chǎn)生,無論是隱式的還是通過=default.這種方式很簡潔,也保證所有數(shù)據(jù)成員都會被復(fù)制.拷貝與移動構(gòu)造函數(shù)一般也更高效,因為它們不需要堆的分配或者是單獨的初始化和賦值步驟,同時,對于類似省略不必要的拷貝這樣的優(yōu)化它們也更加合適.移動操作允許隱式且高效地將源數(shù)據(jù)轉(zhuǎn)移出右值對象.這有時能讓代碼單件類型(Registerer),Cleanup(Mutex)從邏輯上來說都不應(yīng)該提供拷貝操作.為基類提供拷貝/賦值操作是有害的,因為在使用它們時會造成對象切割.默認(rèn)的或者隨意的拷貝操作實現(xiàn)可能是不正確的,這往往導(dǎo)致令人困惑并且難以診斷出的錯誤.拷貝構(gòu)造函數(shù)是隱式調(diào)用的,也就是說,這些調(diào)用很容易被忽略.這會讓人迷惑,尤其是對那些所用的語言約定或強制要求傳引用的程序員來說更是如此.同時,這從一定程度上說會鼓勵過度拷貝,從而導(dǎo)致性能上的問題.結(jié)論:如果需要就讓你的類型可拷貝/可移動.作為一個經(jīng)驗法則,如果對于你的用戶來型可拷貝,一定要同時給出拷貝構(gòu)造函數(shù)和賦值操作的定義,反之亦然.如果讓戶顯然可見,那么把這個類型設(shè)置為只可移動并定義移動的兩個操作.由于存在對象切割的風(fēng)險,不要為任何有可能有派生類的對象提供賦值操作或者拷貝/移動構(gòu)造函數(shù)(當(dāng)然也不要繼承有這樣的成員函數(shù)的類).如果你的基類需要可publicvirtualCloneprotectedpublicdeletevs總述:僅當(dāng)只有數(shù)據(jù)成員時使用struct,其它一概使用class.說明在C++中struct和class關(guān)鍵字幾乎含義一樣.我們?yōu)檫@兩個關(guān)鍵字添加我們自己的語義理解,以便為定義的數(shù)據(jù)類型選擇合適的關(guān)鍵字.struct用來定義包含數(shù)據(jù)的被動式對象,也可以包含相關(guān)的常量,但除了存取數(shù)據(jù)成員之外,.并且存取功能是通過直接訪問位域,而非函數(shù)調(diào)用.除了構(gòu)造函數(shù),析構(gòu)函數(shù)Initialize(Reset(),等類似的用于設(shè)定數(shù)據(jù)成員的函數(shù)外,不能提供其它功能的函數(shù).如果需要更多的函數(shù)功能class更適合.如果拿不準(zhǔn),STL保持一致,class注意:(YuleFox注:GoF<<DesignPatterns>>里反復(fù)強調(diào)的)常常比使用繼承更合理.如果使用繼承的話,定義為public繼承.定義:當(dāng)子類繼承基類時,子類包含了父基類所有數(shù)據(jù)及操作的定義C++實踐中,繼承主要用于兩種場合:實現(xiàn)繼承,子類繼承父類的實現(xiàn)代碼;接口繼承,子類僅繼承父類優(yōu)點:實現(xiàn)繼承通過原封不動的復(fù)用基類代碼減少了代碼量.由于繼承是在編譯時聲明,程序員和編譯器都可以理解相應(yīng)操作并發(fā)現(xiàn)錯誤.從編程角度而言,接口繼承是用來強API.API中某個必須的方法時,編譯器同樣會發(fā)現(xiàn)并缺點:對于實現(xiàn)繼承,由于子類的實現(xiàn)代碼散布在父類和子類間之間,要理解其實現(xiàn)變得更加困難.子類不能重寫父類的非虛函數(shù),當(dāng)然也就不能修改其實現(xiàn).基類也可能定義了一些數(shù)據(jù)成員,因此還必須區(qū)分基類的實際布局.public的.如果你想使用私有繼承,你應(yīng)該替換成把基類的實例作不要過度使用實現(xiàn)繼承.組合常常更合適一些.盡量做到只在“是一個”(“is-a注:其他“has-a”情況下請使用組合)的情況下使用繼承:Bar的確“是一種”Foo,Bar才能繼承Foo.必要的話,virtual.如果你的類有虛函數(shù),則析構(gòu)函數(shù)也應(yīng)該為虛對于可能被子類訪問的成員函數(shù),protected關(guān)鍵字.注意,數(shù)據(jù)成員對于重載的虛函數(shù)或虛析構(gòu)函數(shù),使用override,或(較不常用的)final關(guān)鍵字顯式地進行標(biāo)記.較早(早于C++11)的代碼可能會使用virtual關(guān)鍵字作為不得已的選項.因此,在聲明重載時,請使用override,final或virtual的其中之一進行標(biāo)記.標(biāo)記為override或final的析構(gòu)函數(shù)如果不是對基類虛函數(shù)的重載的話,編譯會報錯,這有助于捕獲常見的錯誤.這些標(biāo)記起到了文檔的作用,因為如果省略這些關(guān)鍵字,代碼閱讀者不得不檢查所有父類,以判斷該函數(shù)是否是虛函數(shù)..承:最多只有一個基類是非抽象類;其它基類都是以Interface為后綴的純接.(見繼承),多重實現(xiàn)繼承可以復(fù)用更多的代碼.有時多重實現(xiàn)繼承看上去是不錯的解決方案,但這時你通常也可以找到一個更明確,更清晰的不同解決方,才允許使用多重繼承.為確保它們是純接口,這些類必須以Interface為后綴.Windowsprivate,staticconst(遵循常量命名規(guī)則出于技術(shù)上的原因,GoogleTest總述:將相似的聲明放在一起,public部分放在最前說明:類定義一般應(yīng)以public:開始,后跟protected:,最后是private:.省略空部分.在各個部分中,建議將類似的聲明放在一起,并且建議以如下的順序:類型(包括typedef,using和嵌套的結(jié)構(gòu)體與類),常量,工廠函數(shù),構(gòu)造函數(shù),賦值運算符,析構(gòu)函數(shù),其它函數(shù),數(shù)據(jù)成員.不要將大段的函數(shù)定義內(nèi)聯(lián)
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024年銀川客運資格證考試內(nèi)容及題型
- 2024年南京道路客運從業(yè)資格證模擬考試試題
- 文化旅游園區(qū)管理辦法
- 餐飲服務(wù)投標(biāo)質(zhì)量承諾書
- 航空公司前臺合同
- 商業(yè)中心堡坎施工合同
- 建筑質(zhì)量文明施工條款
- 旅游區(qū)無線網(wǎng)絡(luò)覆蓋合同
- 樣件成本控制管理提高利潤率
- 交通運輸安全員聘用合同
- 易綱貨幣銀行學(xué)利率的計算
- 陳忠喜——大慶油田采出水處理工藝及技術(shù)最終稿PPT課件
- 第二章思想政治教育的心理基礎(chǔ)
- 園林制圖課件透視
- 實驗室儀器設(shè)備管理培訓(xùn)(課堂PPT)
- 漢語拼音發(fā)音口型及配圖[新版]
- 注塑IPQC培訓(xùn)教材
- 現(xiàn)場技術(shù)服務(wù)確認(rèn)單
- 惡性心律失常及常見心律失常識別與急診處理
- 班主任培訓(xùn)-家校溝通課件
- 砂石項目盈利能力分析報告(范文)
評論
0/150
提交評論