日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁(yè) > 單片機(jī) > 程序喵大人

Part1一、讓自己習(xí)慣C++

條款01:視C++為一個(gè)語言聯(lián)邦

C++并不是一個(gè)帶有一組守則的一體語言:他是從四個(gè)次語言( C、Object-Oriented C++、Template、STL )  組成的聯(lián)邦政府,每個(gè)次語言都有自己的規(guī)約。記住這四個(gè)次于語言你就會(huì)發(fā)現(xiàn)C++容易了解得多。

條款02:盡量以const,enum,inline替換 #define

#define ASPECT_RATIO 1.653

以上句為例,是通過預(yù)處理器處理而不是編譯器處理,有可能ASPECT_RATIO 沒進(jìn)入記號(hào)表內(nèi),于是如果出現(xiàn)了編譯錯(cuò)誤,那么編譯器會(huì)提示錯(cuò)誤信息是 1.653  而不是 ASPECT_RATIO ,你會(huì)感到非常困惑。解決方法是用常量替換宏const double AspectRatio = 1.653這樣編譯器就可以看到ASPECT_RATIO ,而且使用常量會(huì)使代碼量較小,因?yàn)轭A(yù)處理器只會(huì)盲目的替換而出現(xiàn)多份 1.653string對(duì)象通常比char* 更好一點(diǎn)對(duì)于class的專屬常量,為了限制作用域在class內(nèi),并且防止產(chǎn)生多個(gè)實(shí)體,最好使用static
 1. 如果你的編譯器支持在類內(nèi)對(duì)const static 整數(shù)類型聲明時(shí)獲初值,則使用
 2. 如果不支持,則在類內(nèi)定義,在對(duì)應(yīng)的實(shí)現(xiàn)文件中賦值 
如果你需要在編譯器就使用一個(gè)class常量值,則應(yīng)最好改用枚舉類型enum,且枚舉不能用來取地址,不會(huì)為它分配額外的存儲(chǔ)空間對(duì)于形似函數(shù)的宏,最好改用inline的模板函數(shù)

條款 03:盡可能使用const

const出現(xiàn)在星號(hào)左邊目標(biāo)是指物是常量,出現(xiàn)在星號(hào)右邊表示指針本身是常量,如果出現(xiàn)在兩邊,則指針和物都是常量void f1(const Widget* pw)和void f2(Widget const* pw)兩種寫法意義相同,都表示被指物是常量 對(duì)于STL迭代器來說,如果你希望迭代器所指的動(dòng)科不可改動(dòng),你需要的是const_iterator 令函數(shù)返回一個(gè)常量值,往往可以降低因客戶錯(cuò)誤而造成的意外(例如把一個(gè)值賦值給一個(gè)返回值) 將const實(shí)施與成員函數(shù)的目的是為了明確該成員函數(shù)可作用于const對(duì)象:
 1. 他們使class接口比較容易理解
 2. 他們使得可以操作const對(duì)象 
const成員函數(shù)和no-const成員函數(shù)可重載,即可以同時(shí)出現(xiàn),在傳入不同的參數(shù)時(shí)候會(huì)調(diào)用不同的版本,但是有時(shí)我們需要這樣,但是又不想代碼重復(fù),我們可以在no-const成員調(diào)用const成員函數(shù)來處理這個(gè)代碼重復(fù)問題 例如:const_cast( static_cast(*this)[position]);,經(jīng)過這樣里面 先安全轉(zhuǎn)型使得調(diào)用的是const版本,外面再去const轉(zhuǎn)型

條款 04:確定對(duì)象被使用前已先被初始化

對(duì)于內(nèi)置類型要進(jìn)行手工初始化構(gòu)造函數(shù)最好使用成員初值列表,不要在構(gòu)造函數(shù)中使用賦值操作來初始化,而且初值列表列出的成員變量次序應(yīng)該和在class中聲明的次序一樣,因?yàn)槁暶鞔涡蚓褪荂++保證的初始化次序 對(duì)于static對(duì)象,在跨編譯單元之間的初始化次序是不能確定的,因?yàn)镃++只保證在本文件內(nèi)使用之前一定被初始化了舉例(使用如下方式可以解決這個(gè)問題即以loacl static對(duì)象替換non-local static對(duì)象):
class FileSystem{...}; FileSystem& tfs(){ static FileSystem fs; return fs;
}

Part2二、構(gòu)造/析構(gòu)/賦值運(yùn)算

條款05:了解C++默默編寫并調(diào)用了哪些函數(shù)

如果你不定義,編譯器會(huì)自動(dòng)幫你實(shí)習(xí)默認(rèn)的構(gòu)造函數(shù),析構(gòu)函數(shù),拷貝賦值運(yùn)算符和拷貝構(gòu)造函數(shù),但是如下幾種情況不會(huì)替你生成默認(rèn)的拷貝賦值運(yùn)算符
 1. 類中含有**引用**的成員變量
 2. 類中含有**const**的成員變量
 3. 類的**基類**中的拷貝賦值運(yùn)算符是**私有**成員函數(shù) 

條款06:若不想使用編譯器自動(dòng)生成的函數(shù),就應(yīng)該明確拒絕

當(dāng)我們不希望編譯器幫我們生成相應(yīng)的成員函數(shù)的時(shí)候,我們可以將其聲明為private并且不予以實(shí)現(xiàn)

條款07:為多態(tài)基類聲明virtual析構(gòu)函數(shù)

以下情況應(yīng)該為類聲明一個(gè)virtual析構(gòu)函數(shù):
 1. 用來作為帶有多態(tài)性質(zhì)的基類的類
 2. 一個(gè)類中帶有任何virtual函數(shù) 
如果類的設(shè)計(jì)目的不是作為基類使用,那么就不應(yīng)該為它聲明virtual析構(gòu)函數(shù)

條款08:別讓異常逃離析構(gòu)函數(shù)

析構(gòu)函數(shù)不要吐出異常,如果實(shí)在要拋出異常,那么最好使用std::abort();,放在catch中,把這個(gè)行為壓下去 如果某個(gè)動(dòng)作可能會(huì)拋出異常,那么最好把它放在普通函數(shù)中,而不是放在析構(gòu)函數(shù)里面,讓客戶來執(zhí)行這個(gè)函數(shù)并去處理

條款09:絕不再構(gòu)造和析構(gòu)函數(shù)中調(diào)用virtual函數(shù)

在構(gòu)造和析構(gòu)的時(shí)候,不要試圖調(diào)用或在調(diào)用的函數(shù)中調(diào)用virtual函數(shù),因?yàn)闀?huì)調(diào)用父類版本導(dǎo)致出現(xiàn)一些未定義的錯(cuò)誤

解決辦法之一:

class Transaction{ publci: explicit Transaction(const std::string& logInfo); void logTransaction(const std::string& logIngo) const;//把它變成這樣的non-virtual函數(shù) ...
};
Transaction::Transaction(const std::string& logInfo){
 ...
 logTransaction(logInfo);//這樣調(diào)用 } class BuyTransaction: public Transaction{
 BuyTransaction( parameters ):Transaction(createLogString( parameters )){...}//將log信息傳給基類的構(gòu)造函數(shù) private: static std::string createLogString( parameters );//注意此函數(shù)為static函數(shù) }

條款10:令operator= 返回一個(gè)reference to *this

為了實(shí)現(xiàn)連鎖賦值如內(nèi)置類型x= y = z =15由于=采用右結(jié)合律,所以等價(jià)于x = (y = (z = 15)),因此,為了使我們自定義類也實(shí)現(xiàn),所以*重載=,+=,-=,*=使其返回refercence to this

條款11:在operator= 中處理“自我賦值”

在賦值的時(shí)候會(huì)出現(xiàn)對(duì)自我進(jìn)行賦值的情況,這種情況下我們很容易寫出不安全的代碼
Widget::operator=(const Widget& rhs){ delete pb; //把自己釋放了 pb = new Bitmap(*rhs.pb);//這就不安全了 return *this;
}
因此有三種推薦的做法
  1. 先驗(yàn)證是不是相同的,是不是自我賦值
Widget::operator=(const Widget& rhs){ if(this == &rhs) return *this;//驗(yàn)證是不是相同 delete pb; 
 pb = new Bitmap(*rhs.pb); return *this;
}
  1. 在復(fù)制pb所指的東西之前別刪除pb
Widget::operator=(const Widget& rhs){
 Bitmap* pOrig = pb;
 pb = new Bitmap(*rhs.pb);//讓pb指向*pb的一個(gè)副本 delete pOrig; //刪除原先的pb return *this;
}
  1. 使用交換數(shù)據(jù)的函數(shù)
class Widget{ ... void swap(Widget& rhs);//交換*this和rhs的數(shù)據(jù) ...
};
Widget::operator=(const Widget& rhs){
 Widget temp(rhs);//創(chuàng)建一個(gè)rhs副本 swap(temp);//交換*this和上面的副本 return *this;
}

條款12:復(fù)制對(duì)象時(shí)勿忘其每一個(gè)成分

為了確保復(fù)制的時(shí)候復(fù)制對(duì)象內(nèi)的所有成員變量,我們應(yīng)該在字類的構(gòu)造和賦值函數(shù)中調(diào)用父類的構(gòu)造和賦值函數(shù)來完成各自的任務(wù) 不要嘗試在復(fù)制構(gòu)造函數(shù)和賦值函數(shù)中相互調(diào)用,如果想消除重復(fù)代碼,請(qǐng)建立一個(gè)新的成員函數(shù),并且最好將其設(shè)為私有且命名為init

Part3三、資源管理

條款13:以對(duì)象管理資源

為了防止資源泄露,我們應(yīng)該在構(gòu)造函數(shù)中獲取資源,在析構(gòu)函數(shù)中釋放資源,這樣可以有效的避免資源泄露 使用智能指針是一個(gè)好的辦法,在C++11中auto_ptr已經(jīng)被棄用,有三個(gè)常用的是unique_ptr,share_ptr和weak_ptr

條款14:在資源管理類中心copying行為

我們?cè)诠芾鞷AII(構(gòu)造函數(shù)中獲得,析構(gòu)函數(shù)中釋放)觀念的類時(shí),應(yīng)該對(duì)不同的情況,根據(jù)不同的目的進(jìn)行處理
 1. 當(dāng)我們處理不能同步擁有的資源的時(shí)候,可以才用**禁止復(fù)制**,如把copying操作聲明為private
 2. 當(dāng)我們希望共同擁有資源的時(shí)候,可以采用**引用計(jì)數(shù)法**,例如使用shared_ptr
 3. 當(dāng)我們需要拷貝的時(shí)候,可以采用**深拷貝**
 4. 或者某些時(shí)候我們可以采用**轉(zhuǎn)移**底部資源擁有權(quán)的方式 

條款15:在資源管理類中提供對(duì)原始資源的訪問

有的api函數(shù)往往需要訪問類的原始資源,所以每一個(gè)RAII類應(yīng)該提供一個(gè)返回其管理的原始資源的方法 返回原始資源可以使用顯示轉(zhuǎn)換也可以使用隱式轉(zhuǎn)換,但是往往顯示轉(zhuǎn)換更加安全一點(diǎn),但是隱式轉(zhuǎn)換更加方便
class Font{ ... FontHandle get() const {return f;} //顯示轉(zhuǎn)換 ... operator FontHandle() const {return f;} //隱式轉(zhuǎn)換函數(shù) .... private:
 FontHandle f; //管理的原始資源 }

條款16:成對(duì)使用new和delete時(shí)要采用相同形式

不要對(duì)數(shù)組形式做typedef,因?yàn)檫@樣會(huì)導(dǎo)致delete的時(shí)候調(diào)用的是delete ptr而不是delete [] ptr,對(duì)內(nèi)置類型會(huì)出現(xiàn)未定義或有害的,對(duì)類的類型會(huì)導(dǎo)致無法調(diào)用剩余的析構(gòu)函數(shù),導(dǎo)致類中管理的資源無法釋放,從而造成內(nèi)存泄漏 在new 表達(dá)式中使用[ ] ,則在相應(yīng)的delete 表達(dá)式中也使用 [ ]

條款17:以獨(dú)立語句將newed對(duì)象置入智能指針

諸如這樣的語句processWidget (std::tr1::shared_ptr(new Widget),priority())

 1. 在先執(zhí)行new Widget`語句和調(diào)用std::tr1::shared_ptr構(gòu)造函數(shù)之間
 2. 不能確定priority函數(shù)的執(zhí)行順序,可能在最前面,也可能在他們的中間  

Part4四、設(shè)計(jì)與聲明

條款18:讓接口容易被正確使用,不易被誤用

我們接口應(yīng)該替客戶著想,考慮周全,避免它們犯錯(cuò)誤。例如在向函數(shù)傳遞日期的時(shí)候,把日期參數(shù)做成類的形式,并且用static成員函數(shù)來返回固定的月份,避免用戶參數(shù)寫錯(cuò) 接口應(yīng)該和內(nèi)置接口保持一致,避免讓客戶感覺不舒服,這方面STL做的很好 tr1::shared_ptr支持定制型刪除器,使用它可以防范跨DLL構(gòu)建和刪除的問題,可以用它來自動(dòng)解除互斥鎖

條款19:設(shè)計(jì)class猶如設(shè)計(jì)type

謹(jǐn)慎的設(shè)計(jì)一個(gè)類,應(yīng)該遵守以下規(guī)范
 1. 合理的構(gòu)建class的構(gòu)造函數(shù)、析構(gòu)函數(shù)和內(nèi)存分配函數(shù)以及釋放函數(shù)
 2. 不能把初始化和賦值搞混了
 3. 如果你的類需要被用來以值傳遞,復(fù)制構(gòu)造函數(shù)應(yīng)該設(shè)計(jì)一個(gè)通過值傳遞的版本
 4. 你應(yīng)該給你的成員變量加約束條件,保證他們是合法值,所以你的成員函數(shù)必須擔(dān)負(fù)起錯(cuò)誤檢查工作
 5. 如果你是派生類,那么你應(yīng)該遵守基類的一些規(guī)范,如析構(gòu)函數(shù)是否為virtural
 6. 你是否允許你的class有轉(zhuǎn)換函數(shù),,是否允許隱式轉(zhuǎn)換。如果你只允許explicit構(gòu)造函數(shù)存在,就得寫出專門負(fù)責(zé)執(zhí)行轉(zhuǎn)換的函數(shù)
 7. 想清楚你的類應(yīng)該有哪些函數(shù)和成員
 8. 哪些應(yīng)該設(shè)計(jì)為私有
 9. 哪個(gè)應(yīng)該是你的friend,以及將他們嵌套與另一個(gè)是否合理
 10. 對(duì)效率,異常安全性以及資源運(yùn)用提供了哪些保證
 11. 如果你定義的不是一個(gè)新type,而是定義整個(gè)type家族,那么你應(yīng)該定義一個(gè)類模板
 12. 如果只是定義新的字類以便為已有的類添加機(jī)制,說不定單純定義一個(gè)或多個(gè)non-member函數(shù)或模板更好

條款20:寧以pass-by-reference-to-const替換pass-by-value

盡量以pass-by-reference-to-const替換pass-by-value,因?yàn)榍罢咄ǔ1容^高效,比如在含有類的傳遞時(shí),避免了多次構(gòu)造函數(shù)和多次析構(gòu)函數(shù)的調(diào)用,大大的提高了效率 但是對(duì)于某些,比如內(nèi)置類型,迭代器,函數(shù)調(diào)用等最好以值傳遞的形式

條款21:必須返回對(duì)象時(shí),別妄想返回其reference

絕對(duì)不能返回指針或者一個(gè)引用指向一個(gè)臨時(shí)變量,因?yàn)樗嬖跅V校坏┖瘮?shù)調(diào)用結(jié)束返回那么你得到的將是一個(gè)壞指針,也不能使用static變量來解決,你可以通過返回值 來解決

條款22:將成員變量聲明為private

 1. 為了保證一致性
 2. 可以細(xì)微的劃分訪問和控制以及約束
 3. 內(nèi)部更改后不影響使用 

protected并不比public更具封裝性

條款23:寧以non-member、non-friend、替換member函數(shù)

我們可以用non-member、non-friend函數(shù)來替換某些成員函數(shù),可以增加類的封裝性,包裹彈性和擴(kuò)充性

條款24:若所有參數(shù)皆需要類型轉(zhuǎn)換,請(qǐng)為此采用non-member函數(shù)

如果你需要為某個(gè)函數(shù)的所有參數(shù)(包括被this指針?biāo)傅哪莻€(gè)隱喻參數(shù))進(jìn)行類型轉(zhuǎn)換,那么這個(gè)函數(shù)必須是個(gè)non-member

條款25:考慮寫出一個(gè)不拋出異常的swap函數(shù)

在你沒有定義swap函數(shù)的情況下,編譯器會(huì)為你調(diào)用通用的swap函數(shù),但是有的時(shí)候那并不是高效的,因?yàn)槟J(rèn)情況它在置換如指針的時(shí)候把整個(gè)內(nèi)存都置換 我們采取一種解決辦法 1. 在類中提供一個(gè) public swap成員函數(shù),并且這個(gè)函數(shù)不能拋出異常2. 在類的命名空間中提供一個(gè)non-member swap函數(shù),并令它調(diào)用類中的swap函數(shù) 3. 如果你正在編寫一個(gè)類而不是模板類,為你的class特化std::swap函數(shù),并令它調(diào)用你的swap函數(shù) 4. 請(qǐng)?jiān)陬愔新暶?using std::swap,讓其暴露,使得編譯器自行選擇更合適的版本

Part5五、實(shí)現(xiàn)

條款26:盡可能延后變量定義式的出現(xiàn)時(shí)間

定義一個(gè)變量,那么你就得承受這個(gè)變量的構(gòu)造和析構(gòu)的成本時(shí)間,所以在定義一個(gè)變量的時(shí)候我們應(yīng)該盡可能的延后定義時(shí)間,在使用前定義,這樣避免我們定義了卻沒有使用它,造成浪費(fèi)

條款27:盡量少做轉(zhuǎn)型動(dòng)作

舊式轉(zhuǎn)型是C風(fēng)格的轉(zhuǎn)型,C++中提供四種新式轉(zhuǎn)型:
  1. const_cast 通常被用來將對(duì)象的常量性轉(zhuǎn)除。它也是唯一有此能力的轉(zhuǎn)型操作符
  2. dynamic_cast 主要用來執(zhí)行“安全向下轉(zhuǎn)型” ,也就是用來決定對(duì)某對(duì)象是否歸屬繼承體系中的某個(gè)類型。它是唯一無法由舊式語法執(zhí)行的動(dòng)作,也是唯一可能耗費(fèi)重大運(yùn)行成本的轉(zhuǎn)型動(dòng)作
  3. reinterpret_cast 意圖執(zhí)行低級(jí)轉(zhuǎn)型,實(shí)際動(dòng)作(及結(jié)果)可能取決于編譯器,這也就表示它不可移植。例如將一個(gè)pointer to int轉(zhuǎn)型為一個(gè)int。這一類轉(zhuǎn)型在低級(jí)代碼以外很少見。
  4. static_cast 用來強(qiáng)迫隱式轉(zhuǎn)換,例如將non-const對(duì)象轉(zhuǎn)換為const對(duì)象,或?qū)nt轉(zhuǎn)為double等等,它也可以用來執(zhí)行上述多種轉(zhuǎn)換的反向轉(zhuǎn)換,例如將void* 指針轉(zhuǎn)為 type 指針,將pointer-to-base 轉(zhuǎn)為 pointer-ro-derived 。但它無法將 const 轉(zhuǎn)為 non-const ——這個(gè)只有const_cast才能辦到



舊式轉(zhuǎn)型使用的時(shí)機(jī)是,當(dāng)要調(diào)用一個(gè)explicit構(gòu)造函數(shù)對(duì)一個(gè)對(duì)象傳遞給一個(gè)函數(shù)時(shí),其他盡量用新式轉(zhuǎn)型

請(qǐng)記住以下:

 1. 如果可以的話,避免dynamic_cast轉(zhuǎn)型,如果實(shí)在需要,則可以試著用別的無轉(zhuǎn)型方案代替
 2. 如果轉(zhuǎn)型是必要的,那么應(yīng)該把他隱藏于某個(gè)函數(shù)背后,客戶隨后可以調(diào)用該函數(shù),而不是需要將轉(zhuǎn)型放進(jìn)自己的代碼里
 3. 寧可要新型轉(zhuǎn)型,也不要使用舊式轉(zhuǎn)型 

條款28:避免返回handles指向?qū)ο髢?nèi)部成分

避免返回handle(包括引用,指針和迭代器)指向?qū)ο髢?nèi)部。這樣可以增加封裝性,也能把出現(xiàn)空懸指針的可能性降低

條款29:為“異常安全”而努力是值得的

異常安全函數(shù)提供以下三個(gè)保證之一:基本承諾:如果異常被拋出,程序內(nèi)的任何事物仍然保持在有效狀態(tài)下。沒有任何對(duì)象或數(shù)據(jù)會(huì)因此而敗壞,所有對(duì)象都處于一種內(nèi)部前后一致的狀態(tài)。然而程序的現(xiàn)實(shí)狀態(tài)恐怕不可預(yù)料強(qiáng)烈保證:如果異常被拋出,程序狀態(tài)不改變。調(diào)用這樣的函數(shù)需要有這樣的認(rèn)知:如果函數(shù)成功,就是完全成功,如果函數(shù)失敗,程序會(huì)恢復(fù)到“調(diào)用之前”的狀態(tài)不拋擲保證:承諾絕不拋出異常,因?yàn)樗鼈兛偸悄軌蛲瓿伤麄冊(cè)瘸兄Z的功能。作用于內(nèi)置類型身上所有操作都提供nothrow保證,這是異常安全碼中一個(gè)必不可少的關(guān)鍵基礎(chǔ)材料這三種保證是遞增的關(guān)系,但是如果我們實(shí)在做不到,那么可以提供第一個(gè)基本承諾,我們?cè)趯懙臅r(shí)候應(yīng)該想如何讓它具備異常安全性
 1. 首先以對(duì)象管理資源可以阻止資源泄漏
 2. 在你能實(shí)現(xiàn)的情況下,盡量滿足以上的最高等級(jí) 

條款30:透徹了解inlining 的里里外外

inline 聲明的兩種方式:
 1. 隱喻的inline申請(qǐng),即把定義寫在class內(nèi)部
 2. 明確聲明,即在定義式前加上關(guān)鍵字inline 
將大多數(shù)inlining限制在小型、被頻繁調(diào)用的函數(shù)身上。這可使日后調(diào)試和二進(jìn)制升級(jí)更容易,也可使得潛在的代碼膨脹問題最小化。不要只因?yàn)閒unction templates出現(xiàn)在頭文件,就將他們聲明為inline

條款31:將文件間的編譯依存關(guān)系降至最低

支持“編譯依存性最小化”的思想是:相依于聲明式,不要相依于定義式
 1. 頭文件和實(shí)現(xiàn)相分離,頭文件完全且僅有聲明式
 2. 使用創(chuàng)建接口類 

Part6六、繼承與面向?qū)ο笤O(shè)計(jì)

條款32:確定你的public繼承塑模出is-a關(guān)系

public繼承意味著is-a的關(guān)系,即子類是父類的一種特殊化,適合基類的一定適合子類,每個(gè)派生類對(duì)象含有著父類對(duì)象的特點(diǎn)

條款33:避免遮掩繼承而來的名稱

在父類中的名稱會(huì)被字類的名稱覆蓋,尤其是在public繼承下,沒有人希望這樣的發(fā)生 為了避免被遮掩,可以使用using聲明式或轉(zhuǎn)交函數(shù),交給子類

條款34:區(qū)分接口繼承和接口實(shí)現(xiàn)

聲明純虛函數(shù)的目的就是為了讓派生類只繼承函數(shù)接口 聲明虛函數(shù)的目的是讓派生類繼承該函數(shù)的接口和缺省實(shí)現(xiàn) 聲明普通函數(shù)的目的就是讓派生類強(qiáng)制接受自己的代碼,不希望重新定義

條款35:考慮virtual函數(shù)以外的其他選擇

條款36:絕不重新定義繼承而來的non-virtual函數(shù)

任何情況下都不應(yīng)該重新定義一個(gè)繼承而來的non-virtual函數(shù)

條款37:絕不重新定義繼承而來的缺省參數(shù)值

絕對(duì)不要重新定義一個(gè)繼承而來的缺省參數(shù)值,因?yàn)槿笔?shù)值都是靜態(tài)綁定的,而virtual函數(shù)——你唯一應(yīng)該覆寫的東西是動(dòng)態(tài)綁定

條款38:通過復(fù)合塑模has-a或“根據(jù)某物實(shí)現(xiàn)出”

區(qū)分public繼承和復(fù)合 在應(yīng)用領(lǐng)域,復(fù)合意味著一個(gè)中含有另一個(gè),即has-a關(guān)系;在實(shí)現(xiàn)領(lǐng)域意味著根據(jù)某物實(shí)現(xiàn)出

條款39:明智而審慎地使用private繼承

當(dāng)需要復(fù)合時(shí),盡可能的使用復(fù)合,必要時(shí)才使用private: 當(dāng)protected成員或virtual函數(shù)牽扯進(jìn)來的時(shí)候 當(dāng)空間方面的利害關(guān)系,需要尺寸最小化

條款40:明智而審慎地使用多重繼承

多重繼承時(shí)候,如果其父類又繼承同一個(gè)父類,所以解決的方式就是使用virtual繼承,即其父類同時(shí)以virtual繼承那個(gè)父類,但是相應(yīng)的也會(huì)付出一些代價(jià),例如時(shí)間更慢,需要重新定義父類的初始化等,因此設(shè)計(jì)時(shí)最好不要讓這個(gè)父類有任何數(shù)據(jù)成員當(dāng)單一繼承和多重繼承都可以,那么最好選擇單一繼承,多重繼承也有正當(dāng)?shù)挠猛荆梢詫?shí)現(xiàn)同時(shí)public繼承和private繼承的組合

Part7七、模板與泛型編程

條款41:了解隱式接口和編譯期多態(tài)

顯式接口:由函數(shù)的簽名式(也就是函數(shù)名稱、參數(shù)類型、返回類型)構(gòu)成 隱式接口:不基于函數(shù)簽名式,而是由有效表達(dá)式組成 面向?qū)ο蠛头盒途幊潭贾С纸涌诤投鄳B(tài),只不過一個(gè)以顯式為主,一個(gè)以隱式為主 兩種多態(tài)一個(gè)在運(yùn)行期一個(gè)在編譯期

條款42:了解typename的雙重意義

聲明模板參數(shù)的時(shí)候,class和typename是可以互換的,沒什么不一樣 但是標(biāo)識(shí)嵌套從屬類型名稱的時(shí)候必須用typename 不得在基類列(繼承的時(shí)候)或成員初值列(初始化列表)內(nèi)以它作為基類修飾符
templete<typename T> class Derived:public Base::Nested{ //基類列表中不可以加“typename” public: explicit Derived(int x): Base::Nested(x){//mem.init.list中不允許“typename” typename Base::Nested temp; //這個(gè)是嵌套從屬類型名稱 ... //作為一個(gè)基類修飾符需要加上typename }
} 

條款43:學(xué)習(xí)處理模板化基類內(nèi)的名稱

模板化基類指的是當(dāng)派生類的基類是一個(gè)模板
 1. 在基類函數(shù)調(diào)用之前加上  this->
 2. 使用 using 聲明式  ,告訴編譯器,請(qǐng)它假設(shè)這個(gè)函數(shù)存在
 3. 指出這個(gè)函數(shù)在基類中,使用基類::函數(shù)的形式寫出來(不推薦這個(gè),因?yàn)槿绻莢irtual函數(shù),則 會(huì)影響動(dòng)態(tài)綁定)
 但是當(dāng)有模板全特化的時(shí)候,確實(shí)使用的沒有這個(gè)函數(shù),那么依然會(huì)報(bào)錯(cuò) 

條款44:將與參數(shù)無關(guān)的代碼抽離出來

模板生成多個(gè)類和多個(gè)函數(shù),所以任何模板代碼都不該和某個(gè)造成膨脹的模板參數(shù)產(chǎn)生相依關(guān)系 因非類型模板參數(shù)造成的代碼膨脹,往往可以消除,做法是以函數(shù)參數(shù)或類成員變量替換模板參數(shù) 因類型模板參數(shù)造成的代碼膨脹,往往可以降低,做法是讓帶有完全相同的二進(jìn)制表述 的具體類型共享實(shí)現(xiàn)碼

條款45:運(yùn)用成員函數(shù)模板接受所有兼容類型

使用成員函數(shù)模板可以生成接收所有兼容類型的函數(shù) 如果你聲明成員函數(shù)模板用來泛化拷貝構(gòu)造函數(shù)和賦值操作,那么你還需要聲明正常的拷貝構(gòu)造函數(shù)和賦值操作

條款46:需要類型轉(zhuǎn)換時(shí)請(qǐng)為模板定義非成員函數(shù)

當(dāng)我們編寫一個(gè)模板類,它提供的和這個(gè)模板祥光的函數(shù)支持所有參數(shù)的隱式類型轉(zhuǎn)換,請(qǐng)將哪些函數(shù)定義為模板類的內(nèi)部的friend函數(shù)

Part8八、定制new和delete

條款49:了解new—handler的行為

當(dāng)new分配失敗的時(shí)候,它會(huì)先調(diào)用一個(gè)客戶指定的錯(cuò)誤處理函數(shù)(set_new_handler),一個(gè)所謂的new—handler 它是一個(gè)typedef定義出一個(gè)指針指向函數(shù),該函數(shù)沒有參數(shù)也不返回任何東西 set_new_handler的參數(shù)是個(gè)指針指向operator new 無法分配足夠內(nèi)存時(shí)該被調(diào)用的函數(shù)。其返回值也是個(gè)指針,指向set_new_handler 被調(diào)用前正在執(zhí)行(馬上就要被替換)的那個(gè)new—handler函數(shù) 一個(gè)良好設(shè)計(jì)的new—handler函數(shù)必須做以下事情:
 1. 讓更多內(nèi)存可被使用。此策略的一個(gè)做法是,程序一開始就分配一大塊內(nèi)存,而后當(dāng)其第一次被調(diào)用,將它釋還給程序使用
 2. 安裝另一個(gè)new—handler??梢栽O(shè)置讓其調(diào)用另一個(gè)new—handler來替換自己,用來做不同的事情,其做法是調(diào)用set_new_handler
 3. 卸載new—handler,也就是將null指針傳給set_new_handler,這樣new在分配不成功時(shí)拋出異常
 4. 拋出bad_alloc的異常。
 5. 不返回,調(diào)用abort或exit
 6. C++并部支持類的專屬new—handler,但其實(shí)也不需要。你可以令每個(gè)類提供自己的set_new_handler和operator new即可
 set_new_handler允許客戶指定一個(gè)函數(shù),在內(nèi)存分配無法獲得滿足時(shí)調(diào)用。
 Nothrow new是一個(gè)頗為局限的工具,因?yàn)樗贿m用于內(nèi)存分配:后繼的構(gòu)造函數(shù)調(diào)用還是可能拋出異常

條款50:了解new和delete的合理替換時(shí)機(jī)

替換operator new或operator delete的三個(gè)常見理由:用來檢測(cè)運(yùn)用上的錯(cuò)誤 為了收集使用上的統(tǒng)計(jì)數(shù)據(jù) 為了增加分配和歸還的速度 為了降低缺省內(nèi)存管理器帶來的空間額外開銷,也就是實(shí)現(xiàn)內(nèi)存池,可以節(jié)省空間為了彌補(bǔ)缺省分配器中的非最佳齊位 為了將相關(guān)對(duì)象成簇集中 為了獲得非傳統(tǒng)行為了解何時(shí)可在“全局性的”或“class專屬的”基礎(chǔ)上合理替換缺省的new和delete

條款51:編寫new和delete時(shí)需固守常規(guī)

operator new應(yīng)該內(nèi)含有一個(gè)無窮的循環(huán),并在其中嘗試分配內(nèi)存,如果它無法滿足內(nèi)存需求,就該調(diào)用new-handler。它也應(yīng)該有能力處理0 bytes申請(qǐng),即將其按照1 byte分配。Class 專屬版本應(yīng)該處理“比正確大小更大的(錯(cuò)誤)申請(qǐng)”,因?yàn)楫?dāng)有字類繼承的時(shí)候,會(huì)出現(xiàn)傳入的大小和父類大小不同,所以要進(jìn)行判斷形如if(size != sizeof(父類))operator delete應(yīng)該在收到NULL指針的時(shí)候什么也不做,必要時(shí)交給全局的operator new來處理。

條款52:寫了placement new也要寫placement delete

當(dāng)你寫一個(gè)placement operator new ,請(qǐng)確定也寫了對(duì)應(yīng)的placement operator delete版本。如果沒有這樣做,可能回發(fā)生隱微而時(shí)斷時(shí)續(xù)的內(nèi)存泄露當(dāng)你聲明placement new 和placement delete,請(qǐng)確定不要無意識(shí)(非故意)地遮掩正常的全局版本,你如果想提供自定義形式,請(qǐng)內(nèi)含所有正常形式的new和delete或利用繼承機(jī)制及using聲明式

Part9九、雜項(xiàng)討論

條款53:不要輕忽編譯器的警告

不同的編譯器有不同的警告標(biāo)準(zhǔn),要嚴(yán)肅對(duì)待編譯器發(fā)出的警告信息。努力在你的編譯器的最高警告級(jí)別下爭(zhēng)取“無任何警告”的榮譽(yù) 不要過度依賴編譯器的報(bào)警能力,因?yàn)椴煌木幾g器對(duì)待事情的態(tài)度并不相同。一旦移植到另一個(gè)編譯器上,你原本依賴的警告信息有可能消失

條款54:讓自己熟悉包括TR1在內(nèi)的標(biāo)準(zhǔn)程序庫(kù)

C++標(biāo)準(zhǔn)程序庫(kù)的主要機(jī)能由STL、iostream、locales組成。并包含C99標(biāo)準(zhǔn)程序庫(kù)。TR1添加了智能指針(例如 tr1::shared_ptr)、一般化函數(shù)指針(tr1::function)、hash-based容器、正則表達(dá)式以及另外10個(gè)組件的支持 TR1自身知識(shí)一份規(guī)范。為了獲得TR1提供的好處,你需要一份實(shí)物。一個(gè)好的實(shí)物來源是Boost。

條款55:讓自己熟悉Boost

Boost是一個(gè)社群,也是一個(gè)網(wǎng)站。致力于免費(fèi)、源碼開放、同僚復(fù)審的C++程序庫(kù)開發(fā)。Boost在C++標(biāo)準(zhǔn)化過程中扮演具有影響力的角色 Boost提供許多TR1組件實(shí)現(xiàn)品,以及其他許多程序庫(kù)。


本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
關(guān)閉