C++中級(jí)培訓(xùn)教材_第1頁
C++中級(jí)培訓(xùn)教材_第2頁
C++中級(jí)培訓(xùn)教材_第3頁
C++中級(jí)培訓(xùn)教材_第4頁
已閱讀5頁,還剩52頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

附件三:教材模板說明:ー、為便于保存和管理,各類培訓(xùn)教材均采用合訂本。二、教材結(jié)構(gòu):各類培訓(xùn)教材由教材封面、前言、課程目錄、單門課程教材和封底五部分構(gòu)成。三、教材封面:1、封面顏色:教材封面為彩色,工作基本常識(shí)教材為深藍(lán)色,技術(shù)基礎(chǔ)知識(shí)教材為草綠色,管理基礎(chǔ)知識(shí)教材為淺藍(lán)色,營(yíng)銷基礎(chǔ)知識(shí)教材為墨綠色。2、教材名稱:采用“工作基本常識(shí)”“技術(shù)基礎(chǔ)知識(shí)”“管理基礎(chǔ)知識(shí)”“營(yíng)銷基礎(chǔ)知識(shí)”,字體為隸書,黑體,60號(hào)。3、其他標(biāo)識(shí):員エ培訓(xùn)中心編輯采用宋體、黑體、三號(hào),位于教材名稱下面:華為技術(shù)有限公司采用宋體、黑體、小二,位于底端;華為標(biāo)識(shí)位于華為技術(shù)有限公司和員エ培訓(xùn)中心編輯之間;右上角為保密標(biāo)識(shí),楷體,黑體,四號(hào)。四、教材封底:教材封底包括教材名稱、華為技術(shù)有限公司員エ培訓(xùn)中心和時(shí)間、版本號(hào),位于頁面的右下角。五、前言:教材前言為各類培訓(xùn)的目的、課程門類、特點(diǎn)、主要內(nèi)容的簡(jiǎn)介。六、課程目錄:為各門課程排列順序的目錄,統(tǒng)ー編排頁碼,便于學(xué)員查找。七、單門課程教材:各單門課程教材由課程封面、章節(jié)目錄、章節(jié)內(nèi)容、學(xué)習(xí)要求、思考題、參考資料和相關(guān)網(wǎng)站組成。1、課程封面:課程封面為彩色,課程名稱為隸書、60號(hào)、黑體、黑色,左上角為課程編碼。2、章節(jié)目錄:為宋體、小四、黑色3、章節(jié)內(nèi)容:(1)標(biāo)題:章節(jié)目分別以“第一章、第二章、第三章”“1.1、1.2、1.3”和“(1)(2)(3)”來表示。章為宋體、小二、黑體,節(jié)為宋體、四號(hào)、黑體,目為宋體、小四、黑體。(2)文字:每四個(gè)小時(shí)的培訓(xùn)課程,字?jǐn)?shù)控制在10000——20000字之間。教材文字一般為宋體、小四、黑色,行間距為一行半。(3)內(nèi)容:章節(jié)內(nèi)容要有完整的理論體系,不能成為授課膠片的翻版。4、學(xué)習(xí)要求:每章標(biāo)題下面為本章的學(xué)習(xí)要求,以明確本章要掌握的要點(diǎn)。文字為楷體、小四。5、思考題:每章最后要有思考題,以便幫助學(xué)員復(fù)習(xí)、思考。6、參考資料和相關(guān)網(wǎng)站:有參考資料和相關(guān)網(wǎng)站的要附在課程后面,以便幫助學(xué)員查閱。內(nèi)部資料,注意保密C++中級(jí)培訓(xùn)教程員エ培訓(xùn)中心編輯2005年6月VI.0華為技術(shù)華為技術(shù)有限公司

時(shí)言C++語言中級(jí)教材講授C++語言的運(yùn)用技術(shù),包括:類、對(duì)象之間的關(guān)系、對(duì)象的存儲(chǔ)與布局、運(yùn)算符重載、智能指針、仿函數(shù)、泛型編程,C++模式設(shè)計(jì)基本思想。NE002009cVl.01業(yè)務(wù)與軟件C++語言項(xiàng)目C++進(jìn)階TOC\o"1-5"\h\zロ 71.1 Handle-Body與接口、抽象接ロ 7多繼承、與菱形缺陷、this跳轉(zhuǎn)等 13C++多態(tài)的兩種多態(tài)形式和區(qū)別 18第二章 重載 ,?,18函數(shù)重載 ,?,19運(yùn)算符重載 20第三章模板 -29

3.1模塊函3.1模塊函數(shù) -29模塊類 31STL標(biāo)準(zhǔn)模板庫 34附錄:參考資料 ???39前言我們?cè)贑++基礎(chǔ)課程中已經(jīng)了解了C++的ー些基本概念,知道了什么是類什么是對(duì)象。也了解了繼承、封裝、多態(tài)等C++面向?qū)ο蟮幕咎卣?本課程主要是更進(jìn)ー步探討一下C++ー些基本模型的應(yīng)用,加深對(duì)概念的理解,由于課程時(shí)間有限,C++,模型和內(nèi)容又如此之多,對(duì)任何一個(gè)模型都無法深入進(jìn)去,所以只能泛泛而談。第一章類、接口學(xué)習(xí)要求:1、了解類的繼承、封裝等概念之間的關(guān)系2、了解什么是接口,什么是虛函數(shù),它有什么樣的特點(diǎn)。學(xué)會(huì)使用接口編程的思想本章節(jié)主要介紹C++中的類、接口。類,包涵了一組數(shù)據(jù)和一組基于數(shù)據(jù)上的ー組方法。它描述了一個(gè)對(duì)象的屬性、狀態(tài)和行為;接口,它只是描述了一個(gè)對(duì)象的簡(jiǎn)單的行為。有關(guān)類的基本概念:ClassnamesClassmembersMemberFunctionsStaticMemberFunctionsUnionsC++BitFieldsNestedClassDeclarationsTypeNamesinClassScopeMultipleBaseClassesVirtualFunctionsAbstractClassesControllingAccesstoClassMembersprivateMembersprotectedMemberspublicMembersAccessSpecifiersforBaseClasses,priavte,public>protectedFriendsConstructorsDestructorsConversionFunctionsthenewoperatorandthedeleteoperatorCopyingConstructorFunctionsInterface1.1Handle-Body與接口、抽象接口在C++中封裝的概念是把ー個(gè)對(duì)象的外觀接口同實(shí)際工作方式(實(shí)現(xiàn))分離開來,但是C++的封裝是不完全的,編譯器必須知道一個(gè)對(duì)象的所有部分的聲明,以便創(chuàng)建和管理它。我們可以想象一種只需聲明一個(gè)對(duì)象的公共接口部分的編程語言,而將私有的實(shí)現(xiàn)部分隱藏起來。C++在編譯期間要盡可能多地做靜態(tài)類型檢查。這意味著盡早捕獲錯(cuò)誤,也意味著程序具有更高的效率。然而這對(duì)私有的實(shí)現(xiàn)部分來說帶來兩個(gè)影響:ー是即使程序員不能輕易地訪問實(shí)現(xiàn)部分,但他可以看到它:ニ是造成一些不必要的重復(fù)編譯。然而C++并沒有將這個(gè)原則應(yīng)用到二進(jìn)制層次上,這是因?yàn)镃++的類既是描述了一個(gè)接口同時(shí)也描述了實(shí)現(xiàn)的過程,示例如下:classCMyString(private:constintm_cch;char*m_psz;public:CMyString(constchar*psz);-CMyStringO;intLength()const;intIndex(constchar*psz)const;CMyStirng對(duì)外過多的暴露了內(nèi)存布局實(shí)現(xiàn)的細(xì)節(jié),這些信息過度的依賴于這些成員變量的大小和順序,從而導(dǎo)致了客戶過度依賴1SC基本知識(shí) 附錄:名詞解釋于可執(zhí)行代碼之間的二進(jìn)制耦合關(guān)系,這樣的接口不利于跨語言跨平臺(tái)的軟件開發(fā)和移植。1.1.1Handle-Body模式解決這個(gè)問題的技術(shù)有時(shí)叫句柄類(handleclasses)或叫“CheshireCat"[1I0有關(guān)實(shí)現(xiàn)的任何東西都消失了,只剩ー個(gè)單ー的指針“m_pThis”。該指針指向一個(gè)結(jié)構(gòu),該結(jié)構(gòu)的定義與其所有的成員函數(shù)的定義ー樣出現(xiàn)在實(shí)現(xiàn)文件中。這樣,只要接口部分不改變,頭文件就不需變動(dòng)。而實(shí)現(xiàn)部分可以按需要任意更動(dòng),完成后只要對(duì)實(shí)現(xiàn)文件進(jìn)行重新編譯,然后再連接到項(xiàng)目中。這里有這項(xiàng)技術(shù)的簡(jiǎn)單例子。頭文件中只包含公共的接口和一個(gè)簡(jiǎn)單的沒有完全指定的類指針。classCMyStringHandle(private:classCMyString;CMyString*m_pThis;public:CMyStringHandle(constchar*psz);?CMyStringHandle();intLength()const;intIndex(constchar*psz)const;);CMyStringHandle::CMyStringHandle(constchar*psz):m_pThis(newCMyString(psz));(}CMyStringHandle;;-CMyStringHandle()(deletem_pThis;}intCMyStringHandle:;Length()(returnm_pThis->Length();}intCMyStringHandle:;Index(constchar*psz)(returnm_pThis->Index(psz);}這是所有客戶程序員都能看到的。這行classCMyString;是ー個(gè)沒有完全指定的類型說明或類聲明(ー個(gè)類的定義包含類的主體)。它告訴編譯器,Cheshire是ー個(gè)結(jié)構(gòu)的名字,但沒有提供有關(guān)該結(jié)構(gòu)的任何東西。這對(duì)產(chǎn)生一個(gè)指向結(jié)構(gòu)的指針來說已經(jīng)足夠了。但我們?cè)谔峁┅`個(gè)結(jié)構(gòu)的主體部分之前不能創(chuàng)建一1SC基本知識(shí) 附錄:名詞解釋個(gè)對(duì)象。在這種技術(shù)里,包含具體實(shí)現(xiàn)的結(jié)構(gòu)主體被隱藏在實(shí)現(xiàn)文件中。在設(shè)計(jì)模式中,這就叫做Handle-Body模式,Handle-Body只含有一個(gè)實(shí)體指針,服務(wù)的數(shù)據(jù)成員永遠(yuǎn)被封閉在服務(wù)系統(tǒng)中。Handle-Body模式如ド:classHandlem_pThis ノIclass圖1Handle-Body模式(句柄類做為接口)Handle-Body的布局結(jié)構(gòu)永遠(yuǎn)不會(huì)隨著實(shí)現(xiàn)類數(shù)據(jù)成員的加入或者刪除或者修改而導(dǎo)致Hand1e-Body的修改,即Hand1e-Body協(xié)議不依賴于C++實(shí)現(xiàn)類的任何細(xì)節(jié)。這就有效的對(duì)用戶的編譯器隱藏了這些斜街,用戶在使用對(duì)這項(xiàng)技術(shù)時(shí)候,Handle-Body接口成了它唯一的入口。然而Handle-Body模式也有自己的弱點(diǎn):1、接口類必須把每ー個(gè)方法調(diào)用顯示的傳遞給實(shí)現(xiàn)類,這

在ー個(gè)只有一個(gè)構(gòu)造和一個(gè)析構(gòu)的類來說顯然不構(gòu)成負(fù)1SC基本知識(shí) 附錄:名詞解釋擔(dān),但是如果一個(gè)龐大的類庫,它有上百上千個(gè)方法時(shí)候,光是編寫這些方法傳遞就有可能非常冗長(zhǎng),這也增加了出錯(cuò)的可能性。2、對(duì)于關(guān)注于性能的應(yīng)用每ー個(gè)方法都得有兩層的函數(shù)調(diào)用,嵌套的開銷也不理想3、由于句柄的存在依然存在編譯連接器兼容性問題。接口和實(shí)現(xiàn)分離的Handle-Body〇LL2抽象接口使用了“接口與實(shí)現(xiàn)的分離”技術(shù)的Handle-Body解決了編譯器/鏈接器的大部分問題,而C++面向?qū)ο缶幊讨械某橄蠼涌谕瑯邮沁\(yùn)用了“接口與實(shí)現(xiàn)分離”的思想,而采用抽象接口對(duì)于解決這類問題是ー個(gè)極其完美的解決方案。1、抽象接口的語言描述:classIMyString(virtualintLength()const=0;〃這表示是ー個(gè)純虛函數(shù),具有純虛函數(shù)的接口virtualintIndex(constchar*psz)const=0;1SC基本知識(shí) 附錄:名詞解釋2、抽象接口的內(nèi)存結(jié)構(gòu):圖2抽象接口的內(nèi)存布局抽象接口的實(shí)現(xiàn)代碼:接口:classIMyString(virtualintLength()const=0;〃這表示是ー個(gè)純虛函數(shù),具有純虛 〃函數(shù)的接ロvirtualintIndex(constchar*psz)const=0;);實(shí)現(xiàn):classCMyString:publicIMyStringprivate:constintm_cch;char*m_psz;public:CMyString(constchar*psz);virtual-CMyStringO;intLength()const;intIndex(constchar*psz)const;}從上面采用抽象接口的實(shí)例來看,抽象接口解決了Handle-Body所遺留下來的全部缺陷。抽象接口的ー個(gè)典型應(yīng)用:抽象エ廠(AbstractFactroy)MotrfFackXYreturnnewPMButtociCf9t0ScroilBar()CrtMuttonOCwMcnuf)CrBBteScroABart)Crwte8uflon()CreateMwM)Cat?Scro?8ar()0Oo?te6utton()OeateMenuQrMumnewPMMonu1PMFactoryMacFactoryCrMtoScroneart)0?MotrfFackXYreturnnewPMButtociCf9t0ScroilBar()CrtMuttonOCwMcnuf)CrBBteScroABart)Crwte8uflon()CreateMwM)Cat?Scro?8ar()0Oo?te6utton()OeateMenuQrMumnewPMMonu1PMFactoryMacFactoryCrMtoScroneart)0?Cm?s?Buttan()CrMAeMQnuO[ntixnnewMacButton][returnnewMacScrollBa?]returnnewP1SC基本知識(shí) 附錄:名詞解釋圖3抽象工廠模式1.2多繼承與菱形缺陷、this跳轉(zhuǎn)等多重繼承是C++語言獨(dú)有的繼承方式,其它幾乎所有語言都秉承了單ー繼承的思想。這是因?yàn)槎嘀乩^承致命的缺陷導(dǎo)致的:1.2.I菱形缺陷當(dāng)繼承基類時(shí),在派生類中就獲得了基類所有的數(shù)據(jù)成員副本。假如類B從A1和A2兩個(gè)類多重繼承而來,這樣B類就包含Al、A2類的數(shù)據(jù)成員副本??紤]如果Al、A2都從某基類派生,該基類稱為Base,現(xiàn)在繼承關(guān)系如下:圖4麥形繼承關(guān)系我們C++語言來描述這種繼承關(guān)系:classBase{ };classAl:publicBase{ };1SC基本知識(shí) 附錄:名詞解釋classA2:publicBase{ };classB:publicAl,publicA2{ };那么Al、A2都具有Base的副本。這樣B就包含了Base的兩個(gè)副本,副本發(fā)生了重疊,不但增加了存儲(chǔ)空間,同時(shí)也引入了二義性。這就是菱形缺陷,菱形缺陷時(shí)間是兩個(gè)缺陷:1、子對(duì)象重疊2、向上映射的二義性。菱形缺陷的其中一種解決辦法將在C++世界里最廣泛的使用虛擬繼承解決菱形缺陷的應(yīng)用便是標(biāo)準(zhǔn)C++的輸入/輸出iostream;basicjosiostream圖5標(biāo)準(zhǔn)C++的輸入/輸出多重接口與方法名沖突問題(Siamesetwins)對(duì)繼承而來的虛函數(shù)改寫很容易,但是如果是在改寫ー個(gè)“在兩個(gè)基類都有相同原型”的虛函數(shù)情況就不那么容易了。1SC基本知識(shí) 附錄:名詞解釋提出問題:假設(shè)汽車最大速度的接口為ICar,潛艇最大速度的接口為IBoat,有一個(gè)兩棲類的交通工具它可以奔跑在馬路上,也可以航行在大海中,那么它就同時(shí)擁有ICar、IBoat兩種交通工具的最大速度特性,我們定義它的接口為ICarBoat;classICar(virtualintGetMaxSpeed()=0;};classIBoat(virtualintGetMaxSpeed()=0;1;我們先對(duì)ICarBoat的接口做ー個(gè)嘗試:classCCarBoat(virtualintGetMaxSpeed();〃既完成ICar的GetMaxSpeed〇接口方法又 〃完成IBoat的接口方法?顯然不能夠);解決問題:1SC基本知識(shí) 附錄:名詞解釋顯然上面這個(gè)嘗試根本就無法成功,只用ー個(gè)實(shí)現(xiàn)方法,怎么能夠求出這個(gè)ICarBoat交通工具奔跑在馬路上的最高時(shí)速,同時(shí)也能夠求出航行在大海上的最大航行速度呢。上面這ー問題矛盾就在ーー個(gè)方法,卻需要兩個(gè)答案??磥鞩CarBoat要返回兩個(gè)答案就必須有兩個(gè)方法了,我們假設(shè)ー個(gè)方法是求在陸地上奔跑的速度,名稱為GetCarMaxSpeed〇;另ー個(gè)方法是求在大海上航行的最大速度,名稱為GetBoatMaxSpeed();那這兩個(gè)方法又怎么和GetMaxSpeed〇接口方法聯(lián)系起來呢;幸運(yùn)的是,我們找到了解決辦法,而且解決辦法有很多種,下面介紹一下繼承法。classIXCar:publicICar(virtualintGetMaxSpeed(){GetCarMaxSpeed();}virtualintGetCarMaxSpeed()=0;1;classIXBoat:publicIBoat(virtualintGetMaxSpeed()GetBoatMaxSpeed();virtualintGetBoatMaxSpeed()=0;classCCarBoat:publicIXCar,publicIXBoatvirtualintGetCarMaxSpeed()virtualintGetBoatMaxSpeed()1SC基本知識(shí) 附錄:名詞解釋圖6多重接口與方法名沖突問題this跳轉(zhuǎn)this跳轉(zhuǎn)是指的“對(duì)象同一性”問題。在單ー繼承的世界內(nèi),無論繼承關(guān)系怎么復(fù)雜,針對(duì)于同一對(duì)象,無論它的子類或者父類的this指針永遠(yuǎn)相等。即如果有下面的模型:A\(''IハJBJしノ圖7B從A繼承的關(guān)系圖那么對(duì)于ー個(gè)已經(jīng)實(shí)例化B類的對(duì)象bObject,永遠(yuǎn)有(B*)&bObject==(A*)&bObject成立。但是在多繼承的世界內(nèi),上面的等式就不能恒成立,對(duì)象的同一性受到了挑戰(zhàn)。特別的是,在多繼承世界內(nèi)如果圖四的菱形關(guān)系存在情況下,如果對(duì)于已經(jīng)實(shí)例化B類的對(duì)象bObject;(Base*)(Al*)&bObject!=(Base*)(A2*)&bObject成立,當(dāng)這種事情發(fā)生的時(shí)候我們就只能特殊處理了。這種情況在COM應(yīng)用中處處都會(huì)發(fā)生。3C++多態(tài)的兩種多態(tài)形式和區(qū)別C++有兩種多態(tài)多態(tài)形式:1、編譯時(shí)刻多態(tài),編譯時(shí)刻多態(tài)依靠函數(shù)重載或者模板實(shí)現(xiàn)2、運(yùn)行時(shí)刻多態(tài)。運(yùn)行時(shí)刻多態(tài)依靠需函數(shù)虛接口實(shí)現(xiàn)第二章 重載學(xué)習(xí)要求:1、了解什么是函數(shù)重載,什么是運(yùn)算符重載2、學(xué)會(huì)運(yùn)用智能指針,仿函數(shù)在C++的世界里,有兩種重載:函數(shù)重載和運(yùn)算符重載,函數(shù)重載就采用采用參數(shù)匹配的原則,進(jìn)行重載的,它是ー種編譯時(shí)刻的多態(tài)。而運(yùn)算符重載,使采用改寫或者說重新定義C++的內(nèi)嵌運(yùn)算符的方法。1SC基本知識(shí) 附錄:名詞解釋有關(guān)重載的基本概念:OverloadedFunctionsOverloadedOperatorsDeclarationMatchingArgumentMatchingArgumentTypesMatchingArgumentCountsMatchingC++UnaryOperatorsBinaryOperatorsSmartPointerFunctionobjectsI函數(shù)重載函數(shù)重載方法是在當(dāng)前范圍內(nèi)選擇ー個(gè)最佳匹配的函數(shù)聲明供調(diào)用該方法者使用。如果一個(gè)適合的函數(shù)被找到后,這個(gè)函數(shù)將會(huì)被調(diào)用,在這里“適合的”是指按下列順序匹配的符合下面條件的:ー個(gè)精確匹配的函數(shù)被找到一個(gè)參數(shù)只有細(xì)微的差別,幾乎可以忽略不計(jì)的。象類似通過子類向父類轉(zhuǎn)化達(dá)到參數(shù)匹配的4、通過正常轉(zhuǎn)化函數(shù)進(jìn)行類型轉(zhuǎn)換,能夠達(dá)到參數(shù)匹配到的。5、通過用戶自定義的轉(zhuǎn)化函數(shù)(如轉(zhuǎn)化運(yùn)算符或者構(gòu)造函數(shù))達(dá)到參數(shù)匹配的1SC基本知識(shí) 附錄:名詞解釋6、參數(shù)是采用省略符號(hào)函數(shù)重載的方法基本上有:根據(jù)函數(shù)參數(shù)數(shù)據(jù)類型的不同進(jìn)行的重載;根據(jù)參數(shù)個(gè)數(shù)的不同進(jìn)行的重載;缺省參數(shù)上的重載我們?cè)谶@里把缺省參數(shù)也稱為ー種函數(shù)重載,實(shí)際上它并不是嚴(yán)格意義上的重載。在使用缺省參數(shù)時(shí)必須記住兩條規(guī)則。第一,只有參數(shù)列表的后部參數(shù)才可是缺省的,也就是說,我們不可以在ー個(gè)缺省參數(shù)后面又跟ー個(gè)非缺省的參數(shù)。第二,一旦我們開始使用缺省參數(shù),那么這個(gè)參數(shù)后面的所有參數(shù)都必須是缺省的。第三,缺省參數(shù)只能放在函數(shù)聲明中。第四,缺省參數(shù)可以讓聲明的參數(shù)沒有標(biāo)識(shí)符。返回值重載特別注意,在C++中并沒有根據(jù)返回返回值的不同進(jìn)行重載的,即我們不能定義這樣的函數(shù):voidf();intf();在C++中這樣的函數(shù)聲明方法是被禁止的,但是我們有時(shí)間可能又需要這樣的重載方法,我們又怎么實(shí)現(xiàn)呢,其實(shí)很簡(jiǎn)單,jiang函數(shù)的參數(shù)進(jìn)行擴(kuò)展,將這個(gè)函數(shù)返回值的數(shù)據(jù)類型,做為擴(kuò)展參數(shù)的數(shù)據(jù)類型來。如下:voidf(void);1SC基本知識(shí) 附錄:名詞解釋voidf(int);此時(shí)這個(gè)例子中的參數(shù)列表的數(shù)據(jù),只在編譯時(shí)刻起到分練函數(shù)的作用,在運(yùn)行時(shí)刻并不起到傳值作用,模板中經(jīng)常都應(yīng)用到了這種方法。1.2運(yùn)算符重載你可以重新定義C++絕大多數(shù)內(nèi)嵌運(yùn)算符的實(shí)現(xiàn)方法和功能,這些重定義的或者說重載的運(yùn)算符,有可能全局作用的,也有可能作用在類基礎(chǔ)之上的,運(yùn)算符重載的實(shí)現(xiàn)可能以類的成員函數(shù)的形式出現(xiàn),也有可能以全局性的函數(shù)的身份出現(xiàn)。在C++中重載運(yùn)算符的名字為〇peratorx,在這里x是ー個(gè)可重載的運(yùn)算符,如:重載加法運(yùn)算符,你需要定義ー個(gè)名為operator+的函數(shù),然后實(shí)現(xiàn)他,其它的類似定義就可以了,例如:Classcomplex//verysimplifiedcomplex]doublere,im;public:complex(doubler,doublei):re(r),im(i){};complexoperator+(complex);complexoperator*(complex);;定義了complex這個(gè)復(fù)數(shù)的ー個(gè)簡(jiǎn)單的實(shí)現(xiàn)概念模型。ー個(gè)復(fù)數(shù)是由一對(duì)double類型的數(shù)據(jù)組成,并定義了這個(gè)復(fù)數(shù)的兩個(gè)方法,加法運(yùn)算complex::operartor+()和乘法運(yùn)算complex::operator*().現(xiàn)在我們就能夠?qū)崿F(xiàn)下面的復(fù)數(shù)表達(dá)式了:voidf()complexcomplex(1,3.1);complexcomplex(1,3.1);complexbcomplex(1.2,2);complexc*a;c=a*b+complex(1,2);C++可重載的和C++不可重載的運(yùn)算符可重載運(yùn)算符表:OperatorNameTypeOperatorNameOperatorNameTypeOperatorNameCommaBinary->*Pointer-to-memberselectionCommaBinary->*1*LogicalNOTUnary/Division1=InequalityBinary/=Division/assignmen%ModulusBinary<Lessthan%=Modulus/assignmentBinary?Leftshift&BitwiseANDBinary?=Leftshift/assignment&Address-ofUnary<=Lessthanorequalt&&LogicalANDBinary—Assignment&二BitwiseAND/assignBinary——Equality()Functioncall—>Greaterthan*MultiplicationBinary>=Greaterthanorequalto*PointerdereferenceUnary?Rightshift*二Muitiplication/assignBinary?=Rightshift/assignment+AdditionBinary[]Arraysubscript+UnaryPlusUnaryへExclusiveOR++Increment1UnaryへExclusiveOR/assignment+二Addition/assignmentBinary1Bitwiseinclusive0—SubtractionBinary1=BitwiseinclusiveOR/assignment—UnarynegationUnaryIILogicalOR——Decrement1UnaryOne'scomplement-- Subtraction/assign Binarydelete delete-> Memberselection Binarynew不可重載運(yùn)算符表:OperatorName*Memberselection.*Pointer-to-memberselection????Scoperesolution9???Conditional#Preprocessorsymbol##Preprocessorsymbol在上面可重載的運(yùn)算符可以看出運(yùn)算符重載共分為兩類:一元運(yùn)算符重載和二元運(yùn)算符重載一元運(yùn)算符重載:在聲明一個(gè)類的非靜態(tài)的一元運(yùn)算符重載函數(shù)時(shí),你必須聲明的形式如 下:ret-typeoperator*() (1)在這里ret-type是指返回?cái)?shù)據(jù)類型op是指一元運(yùn)算符1SC基本知識(shí) 附錄:名詞解釋在聲明一個(gè)全局的一元運(yùn)算符重載函數(shù)時(shí),你必須聲明的形式日下:ret-typeoperator4^arg)(2)在這里ret-type與op和上面的意思ー樣,arg是指這個(gè)運(yùn)算符所作用的數(shù)據(jù)類型二元運(yùn)算符重載:在聲明一個(gè)類的非靜態(tài)的二元運(yùn)算符重載函數(shù)時(shí),你必須聲明的形式如 下:ret-typeoperator。ク(財(cái)ノ (3)(3)式和二式基本相同arg可以是任何ー個(gè)在聲明一個(gè)全局的二元運(yùn)算符重載函數(shù)時(shí),你必須聲明的形式日下:ret-typeoperator0ク(財(cái)aZ,arg2)(4)在這里ret-type與op和上面的意思ー樣,argl,arg2,是指這個(gè)運(yùn)算 符所作用兩個(gè)數(shù)據(jù)類型幾類特殊的運(yùn)算符重載1、類型轉(zhuǎn)換運(yùn)算符所有的數(shù)據(jù)類型均可以定義構(gòu)造函數(shù),包括系統(tǒng)定義的數(shù)據(jù)類型和用戶自定義的數(shù)據(jù)類型,如:classCStringoperatorLPCSTR()const;應(yīng)用:CStringstr="12345”;LPCSTRIpsz=str;〃此處會(huì)進(jìn)行LPCSTR運(yùn)算這只是一個(gè)簡(jiǎn)單的應(yīng)用的示例,其實(shí)有時(shí)間類型轉(zhuǎn)換具有無比強(qiáng)大的功能。我曾經(jīng)就是用類型裝換運(yùn)算符重載解決ー個(gè)跨平臺(tái)通信的問題。2、bool運(yùn)算符重載int、float、bool等運(yùn)算符也是可以重載的,例如重載bool運(yùn)算符,但是重載運(yùn)算符bool時(shí)候,需要注意有很多麻煩和臆想不到的東西template<classT>classtestbooloperatorbool()constthrow()(returnm_pT!=0;private:T*m_pT;1SC基本知識(shí) 附錄:名詞解釋}下面結(jié)果均通過編譯testbool<int>spl;testbooKstd::string>sp2;if(spl==sp2)if(spl!=sp2)boolb=splintI=spl*10;從上面可以看得出bool的表現(xiàn)已經(jīng)遠(yuǎn)遠(yuǎn)超過bool本身了,所以建議大家不要輕易對(duì)bool進(jìn)行重載操作。3、地址運(yùn)算符重載在DCOM應(yīng)用中,我們有一個(gè)重載運(yùn)算符的例子:STDAPICoCreatelnstance(REFCLSIDrclsid,LPUNKNOWNpUnkOuter,DWORDdwClsContextyREFIIDriidfLPVOID*ppレ);我們看最后ー個(gè)參數(shù)LPVOID指針的指針,這里是ー個(gè)輸出參數(shù),返回一個(gè)接口的指針。一般情況下我們應(yīng)用如下IUnknown*pUn;CoCreatelnstance,(void**)&pUn);然而我們也可以這樣寫:IUnknown*pUn;CComPtrcomPtr(pUn);CoCreateInstance(,(void**)&comPtr);之所以能夠這么寫這是因?yàn)镃ComPtr重載了“&”運(yùn)算符,如下:template<classT>classCComPtr(public:CComPtr(T*Ip)(if((p=lp)!=NULL)p->AddRef();}T**operator&()(ATLASSERT(p==NULL);return&p;)private:T*p;};&comPtr實(shí)際上是得到了一般的情況下,我們并不能對(duì)pUn的地址,所以(5)式和式其實(shí)傳入的參數(shù)是ー樣當(dāng)都是傳入了pUn的地址。1SC基本知識(shí) 附錄:名詞解釋雖然我們能夠?qū)\(yùn)算符進(jìn)行重載,但一般情況下我們并不是很提倡這種操作,這是因?yàn)?暴露了封裝對(duì)象的地址,如上面CComPtr對(duì)pUn的封裝其實(shí)不起任何作用,任何時(shí)候我都可以直接訪問和修改pUn指針,這就意味著所有權(quán)的完全喪失,封裝不起任何意義對(duì)于unaryoperator&的重載使得重載對(duì)方永遠(yuǎn)無法與STL容器進(jìn)行任何融合,甚至無法參與任何泛型編程。ー個(gè)對(duì)象的地址是ー個(gè)對(duì)象最基本的概念,在一般情況下,我們并不提倡,也請(qǐng)大家慎用地址運(yùn)算符的重載。4、指針運(yùn)算符重載指針運(yùn)算符,有一個(gè)及其特殊且及其重要的機(jī)制:當(dāng)你對(duì)某個(gè)型別實(shí)施。perator-〉而這個(gè)型別并非原生指針時(shí)候:編譯器會(huì)從這個(gè)型別中找出用戶自定義的operator->?并實(shí)施后,編譯器將繼續(xù)對(duì)這個(gè)operator-〉返回的結(jié)果實(shí)施operator-)直到找到ー個(gè)原生指針。這種機(jī)制導(dǎo)致了一個(gè)特有的技術(shù):(preandpostfunctioncalls),“前調(diào)用”及后調(diào)用技術(shù)。應(yīng)用如下:classCallDoSomething(public:voidDoCallQTRACE("DoCall\n");)};template<classT>classCalllnMutiThread(classLockProxy(public:LockProxy(T*pT):m_pT(pT)(TRACE("Lock\n");}~LockProxy()(TRACE("UnLock\n");}T*operator->()(returnm_pT;)private:T*m_pT;};public:CallInMutiThread(T*pT):m_pT(pT)LockProxyoperator->()(returnLockProxy(m_pT);}private:T*m_pT;};上面CallDoSomething是函數(shù)調(diào)用,假設(shè)這個(gè)類原來是在單線程中運(yùn)行的,但是現(xiàn)在已經(jīng)移植到了多環(huán)境中,所以我們就增加了CalllnMutiThread對(duì)原始類進(jìn)行配接使之適應(yīng)與多線程環(huán)境,調(diào)用過程如下:CallDoSomethingDoSomthing;CallInMutiThread<CallDoSomething>MutiThread(&DoSomthing);MutiThread->DoCall();調(diào)用結(jié)果如下:LockDoCallUnLock從上面可以看出在調(diào)用CallDoSomething的成員函數(shù)DoCall之前調(diào)用了Lock方法,在調(diào)用結(jié)束后有調(diào)用了UnLock〇這就是所謂的“前調(diào)用”和“后調(diào)用”,其實(shí)并不僅僅是多線程問題可以采用此辦法,所有的“前調(diào)用”和“后調(diào)用”模式均可由此解。重載“ー〉”運(yùn)算符,同時(shí)引出了智能指針的概念,參見下頁。5、括號(hào)運(yùn)算符重載語法特征:primary-expression(expression-listop{)1SC基本知識(shí) 附錄:名詞解釋括號(hào)運(yùn)算符是ー個(gè)同“ー〉”運(yùn)算符ー樣也是ー個(gè)及其重要的運(yùn)算符在MSDN上說括號(hào)運(yùn)算符是ー個(gè)二元運(yùn)算符,我覺得這個(gè)說法是完全錯(cuò)誤的,在所有C++運(yùn)算符重載中,括號(hào)運(yùn)算符,應(yīng)該是唯一沒有規(guī)定參數(shù)元的個(gè)數(shù)的。它的參數(shù)可以從0個(gè)至UN個(gè)。示例:classPoint(public:Point(){_x=_y=0;}Point&operator()(intdx,intdy){_x+=dx;_y+=dy;return*this;}private:int_x,_y;};調(diào)用如下:Pointpt;pt(3,2);從上面可以看出,括號(hào)運(yùn)算符,調(diào)用形式如下:object(parameterlist);看起來和函數(shù)的形式是完全一樣的:function{parameterlist);所以根據(jù)這ー特點(diǎn)我們稱之為仿函數(shù)。第三章 模板學(xué)習(xí)要求:1、了解什么是模板2、學(xué)會(huì)運(yùn)用模板函數(shù),模版類和SIL模板(templates),以及以模版為基礎(chǔ)的泛型編程和泛型模式,是當(dāng)今C++中最活躍的ー項(xiàng)編程技術(shù),模版的第一個(gè)革命性的應(yīng)用就是StandardTemplateLibrary(簡(jiǎn)稱STL)〇STL將templates技術(shù)廣泛應(yīng)用于STL容器和STL算法上,在這ー領(lǐng)域template技術(shù)發(fā)揮到了極致。本章介紹C++templates的基本概念和語言特性認(rèn)識(shí)模板1、模板的基本語法是:template<[typelist][,[arglist]]>declaration這個(gè)template描述了一個(gè)參數(shù)化的類(模板類)或者是ー個(gè)參數(shù)化的函數(shù)(模板函數(shù)),這個(gè)模板參數(shù)列表是用逗號(hào)分隔的類型列表(在這個(gè)表單忠使用class或者是typename來標(biāo)識(shí)這個(gè)數(shù)據(jù)類型)。在某些情況下這個(gè)模板體內(nèi)可能不存在任何的數(shù)據(jù)類型。declaration域必須是一個(gè)函數(shù)或者類的聲明。1SC基本知識(shí) 附錄:名詞解釋L4模板函數(shù)語法定義:template<comma-separated_1ist-of-parameters>function-name(parameterlist){}例如:template<typenameT>inlineTconst&max(Tconst&a,Tconst&b){//ifa<bthenusebelseuseareturna<b?b:a;}調(diào)用形式:1:通過調(diào)用的參數(shù)來識(shí)別模板的各參數(shù)類型MAX(4,4.2);//OK,buttypeoffirstargumentdefinesreturntype2r明確指定參數(shù)的類型:MAX<int,fIoat>(4,4.2);//OK在我們的例子中這個(gè)參數(shù)列表是typenameT,其實(shí)在這里typename是可以用class替換的,typename是在C++演化過程中逐漸形成的,而class是ー個(gè)歷史性的概念,typename表達(dá)了ー個(gè)比class更抽象意義上的概念。有如下定義如:classtypenamedef(typedefintINT_TYPE;};如果這樣表達(dá)是正確的:template<classT>classtesttypename:publictypenamedef(public:typenameT::INT_TYPE;INT_TYPEmjnt;1;但是如果把此處的typename換成class就會(huì)報(bào)錯(cuò)1.4.1重載模板函數(shù)(OverloadingFunctionTemplates)和普通的函數(shù)一樣,模板函數(shù)也可以被重載,也就是說對(duì)象同的函數(shù)名,你能夠具有不同的函數(shù)定義,在調(diào)用的時(shí)候再由C++編譯器決定,那一個(gè)候選函數(shù)更有資格被匹配調(diào)用。下面這個(gè)簡(jiǎn)單的例子說明了重載模板函數(shù)的方法和過程://maximumoftwointvaluesinlineintconst&max(intconst&a,intconst&b)(returna<b?b:a;)//maximumoftwovaluesofanytypetemplate<typenameT>inlineTconst&max(Tconst&a,Tconst&b){returna<b?b:a;}//maximumofthreevaluesofanytypetemplate<typenameT>inlineTconst&max(Tconst&a,Tconst&b,Tconst&c)returnmax(max(a,b),c);}intmain()(::max(7,42,68); //callsthetemplateforthreearguments::max(7.0,42.0); //callsmax<double>(byargumentdeduction)::max('a','b'); //callsmax<char>(byargumentdeduction)::max(7,42); //callsthenontemplatefortwoints::max<>(7,42); //callsmax<int>(byargumentdeduction)::max<double>(7,42);//callsmax<double>(noargumentdeduction)}上面這個(gè)例子也說明了普通的函數(shù)與模板函數(shù)可以擁有同ー個(gè)名字,而且可以被初始化為同一類型,如:max(7,42)調(diào)用匹配非模板函數(shù)也匹配模板函數(shù)。1.5模板類基本的語法定義:template<comma-separated-list-of-parameters>classclass-name{??????);具有缺省參數(shù)的模板定義形式template<typenameT,typenameAlloc=alloc>classclass-name|??????};在模板中用到了大量非習(xí)慣性思維方法,大家在學(xué)習(xí)模板之前需要了解這些模板設(shè)計(jì)的思維方法:申明并不一定需要定義:1、申明一個(gè)函數(shù),并不實(shí)現(xiàn)在C++中我們可能因?yàn)榻鼓硞€(gè)缺省函數(shù)的調(diào)用操作而申明該缺省函數(shù),但不定以它,例如:classtestDeclare(public:testDeclare();};我們對(duì)上面的testDeclare的缺省構(gòu)造函數(shù)進(jìn)行了聲明,但是我們并沒有構(gòu)造函數(shù)的的定義,當(dāng)我們執(zhí)行testDeclaredeclare;上面這個(gè)申請(qǐng)創(chuàng)建一個(gè)對(duì)象的操作會(huì)被編譯系統(tǒng)所禁止當(dāng)然,我們也可以對(duì)缺省的重載運(yùn)算符實(shí)施同樣的手段2、申明一個(gè)函數(shù)而不實(shí)現(xiàn)可能是為了模板函數(shù)的泛化泛化:template<typenameT>TtestFun();特化:templateointtestFun()(return10;}3、申明一個(gè)函數(shù)可能僅僅為了獲得特殊某ー項(xiàng)功能例如:TMarkT();charTest(T);intTest(...);sizeof(MarkT());上面的例子其實(shí)就是求T類的的字節(jié)數(shù),其實(shí)在一般情況下,我們直接寫sizeof(T)就可以了,然而有的時(shí)候系統(tǒng)并不允許我們這樣做,所以我們就可以通過上面的例子MarkT〇函數(shù),其實(shí)上面的MarkT(),charTest(T)函數(shù)intTest(...)都是沒有定義的,但是由于sizeof是編譯時(shí)刻的運(yùn)算,所以它并不需要關(guān)心這些函數(shù)是否實(shí)現(xiàn)。?申明一個(gè)類而不實(shí)現(xiàn)例如我們?cè)诮鼓0孱惖姆夯^程中就可以實(shí)現(xiàn)template<typenameT>classtestClass;〃泛化只申明templateoclasstestClass<int>〃特化進(jìn)行實(shí)現(xiàn)();如果我們有testClass<char>test;//error〃系統(tǒng)會(huì)調(diào)用泛化時(shí)發(fā)現(xiàn)沒有沒有實(shí)現(xiàn)二產(chǎn)生編譯錯(cuò)誤testClass<int>test;//OK〃系統(tǒng)調(diào)用特化故OK模板設(shè)計(jì)基本方法編譯器斷言template<classT,classU>(typedefcharsmall;classbig{chardummy[2]};staticsmalltest(U);staticbigtest(...);staticTmarkT(); 〃函數(shù)定義只是為了得到ー個(gè)返回類型public;enum{value=sizeof(test(makT()))==sizeof(Small)};};模板特化template<typenameI,typenameO>structtestClass(testClass(){count?"I,O"?endl;}};template<typenameT>structtestClassvT*,T*>(testClass(){count?"T*,T*"?endl;}};常數(shù)映射型別template<intv>structtestClass{enum{value=v};};型別映射型別template<typenameT>structtestClass(typedefTOriginalType;);1.6STL標(biāo)準(zhǔn)模板庫容器?序列容器-vector,list>deque>stack(沒有迭代器)、queue(沒有迭代器)、即stack、queue不允許遍歷行為?關(guān)聯(lián)容器-set(標(biāo)準(zhǔn))、map(標(biāo)準(zhǔn))、hashtable、RB-tree通用算法,begin()>end()>size()>empty()>erase(iteratorposition)、clear()1SC基本知識(shí) 附錄:名詞解釋迭代器迭代器的基本算法能夠進(jìn)行+、ー、++、ー、+;、ー:、ニ二、!二等運(yùn)算,是ー種智能性指針,實(shí)現(xiàn)operator*operator-)的重載根據(jù)迭代器的特點(diǎn),迭代器又稱循環(huán)子迭代器前閉后開區(qū)間[first,last)型別單向迭代器??赡娴?。隨機(jī)迭代器迭代器的繼承關(guān)系1SC基本知識(shí) 附錄:名詞解釋InputIteratorOutputIteratorForwardItera

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論