C++高級(jí)編程五v1.2 暗影行者_(dá)第1頁
C++高級(jí)編程五v1.2 暗影行者_(dá)第2頁
C++高級(jí)編程五v1.2 暗影行者_(dá)第3頁
C++高級(jí)編程五v1.2 暗影行者_(dá)第4頁
C++高級(jí)編程五v1.2 暗影行者_(dá)第5頁
已閱讀5頁,還剩120頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

1、1C C+高級(jí)編程高級(jí)編程 ( (五五) )聯(lián)航精英訓(xùn)練營2C+C+的多態(tài)性的多態(tài)性3多態(tài)性多態(tài)性n 多態(tài)性(polymorphism)是面向?qū)ο蟪绦蛟O(shè)計(jì)的主要特征之一。多態(tài)性對(duì)于軟件功能的擴(kuò)展和軟件重用都有重要的作用。n 多態(tài)性:發(fā)出同樣的消息被不同類型的對(duì)象接收導(dǎo)致完全不同的行為;n 面向?qū)ο蟪绦蛟O(shè)計(jì)中多態(tài)性表現(xiàn)為以下幾種形式:p重載多態(tài):通過調(diào)用相同名字的函數(shù),表現(xiàn)出不同的行為。運(yùn)算符重載也是一種重載多態(tài)。p運(yùn)行多態(tài):通過基類的指針,調(diào)用不同派生類的同名函數(shù),表現(xiàn)出不同的行為。p模板多態(tài),也稱為參數(shù)多態(tài):通過一個(gè)模板,得到不同的函數(shù)或不同的類。這些函數(shù)或者類具有不同的特性和不同的行為。4

2、多態(tài)的實(shí)現(xiàn)多態(tài)的實(shí)現(xiàn): :聯(lián)編聯(lián)編n 聯(lián)編(binding)一個(gè)具有多態(tài)性的程序語句,在執(zhí)行的時(shí)候,必須確定究竟是調(diào)用哪一個(gè)函數(shù)。也就是說,在執(zhí)行的時(shí)候調(diào)用哪個(gè)函數(shù)是唯一的確定的,確定具有多態(tài)性的語句究竟調(diào)用哪個(gè)函數(shù)的過程稱為聯(lián)編(binding),有的資料也翻譯成“綁定”。n 聯(lián)編有兩種方式:靜態(tài)聯(lián)編和動(dòng)態(tài)聯(lián)編p 靜態(tài)聯(lián)編:在程序編譯時(shí)刻就能決定調(diào)用的是哪個(gè)函數(shù),因此靜態(tài)的多態(tài)性又稱編譯時(shí)的多態(tài)性 主要靠函數(shù)重載和操作符重載實(shí)現(xiàn)。p 動(dòng)態(tài)的多態(tài)性(動(dòng)態(tài)束定)在程序的運(yùn)行過程中動(dòng)態(tài)確定操作所指的對(duì)象,因此又稱運(yùn)行時(shí)的多態(tài)性。 主要靠虛函數(shù)實(shí)現(xiàn)。5例子例子-t1.cpp-t1.cpp#inclu

3、de using namespace std;class Pointpublic: Point(double i,double j)x=i; y=j; double area()const return 0;private: double x, y;class Rectangle:public Pointpublic: Rectangle(int i, int j, int k, int l); double area() const return w*h;private: double w, h;Rectangle:Rectangle(int i,int j,int k,int l):Poi

4、nt(i,j) w=k; h=l;void fun(Point &s) couts.area()endl;int main() Rectangle rect(3.0,5.2,15.0,25.0); fun(rect); return 0;輸出:0結(jié)果不是我們想要的,如何處理?6虛函數(shù)虛函數(shù)n 虛函數(shù)是動(dòng)態(tài)綁定的基礎(chǔ);p 說明方法: virtual() 在基類的函數(shù)的前面加上virtual關(guān)鍵字,那么所有的派生類都自動(dòng)加上virtual關(guān)鍵字,故派生類的virtual關(guān)鍵字可以省略 優(yōu)勢:通過動(dòng)態(tài)綁定可以使我們?cè)诰帉懗绦驎r(shí),使用繼承層次中任意類型的對(duì)象,無須關(guān)心對(duì)象的具體類型,使用這些類

5、的程序無須區(qū)分函數(shù)是在基類還是在派生類中定義的。p 含義: 若類中一成員函數(shù)被說明為虛函數(shù),則該成員函數(shù)在派生類中可能有不同的實(shí)現(xiàn)。當(dāng)使用該成員函數(shù)操作指針或引用所標(biāo)識(shí)的對(duì)象時(shí),對(duì)該成員函數(shù)調(diào)用可采用動(dòng)態(tài)綁定方式。7繼承類圖繼承類圖-t7.cpp-t7.cpp8虛函數(shù)例子虛函數(shù)例子#include using namespace std;class Pointpublic: Point(double i,double j)x=i;y=j; virtual double area()const return 0;private: double x,y;class Rectangle:public

6、 Pointpublic: Rectangle(int i,int j,int k,int l); virtual double area() const return w*h;private: double w,h;Rectangle:Rectangle(int i,int j,int k,int l):Point(i,j) w=k; h=l;/void fun(Point s) 結(jié)果將如何?void fun(Point &s) couts.area()endl;int main() Rectangle rect(3.0,5.2,15.0,25.0); fun(rect); retu

7、rn 0;輸出:3759例子例子-t2.cpp-t2.cpp#include using namespace std;/虛函數(shù)的晚綁定只有對(duì)指針和引用有效class Basepublic: virtual int area() return 6; ;class Derived: public Basepublic: int area() return 12; ;int main() Base b; Derived d; coutb.area()endl; coutd.area()endl; b = d; coutb.area()endl; Base *b1 = new Derived; cou

8、tarea()endl; return 0;10動(dòng)態(tài)束定實(shí)現(xiàn)的三個(gè)條件動(dòng)態(tài)束定實(shí)現(xiàn)的三個(gè)條件n 要實(shí)現(xiàn)運(yùn)行時(shí)的多態(tài),需要以下條件:公共繼承是基礎(chǔ);基類要有說明的是虛函數(shù);調(diào)用虛函數(shù)操作的是指向?qū)ο蟮闹羔樆蛘邔?duì)象引用;或者是由成員函數(shù)調(diào)用虛函數(shù);11虛函數(shù)有哪些限制虛函數(shù)有哪些限制? ?1. 如果虛函數(shù)在基類與派生類中出現(xiàn),僅僅是名字相同,而形式參數(shù)不同,或者是返回類型不同,那么即使加上了virtual關(guān)鍵字,也是不會(huì)進(jìn)行滯后聯(lián)編的。2. 只有類的成員函數(shù)才能說明為虛函數(shù),因?yàn)樘摵瘮?shù)僅適合用于有繼承關(guān)系的類對(duì)象,所以普通函數(shù)不能說明為虛函數(shù)。3. 靜態(tài)成員函數(shù)不能是虛函數(shù),因?yàn)殪o態(tài)成員函數(shù)的特點(diǎn)

9、是不受限制于某個(gè)對(duì)象。4. 內(nèi)聯(lián)(inline)函數(shù)不能是虛函數(shù),因?yàn)閮?nèi)聯(lián)函數(shù)不能再運(yùn)行中動(dòng)態(tài)確定位置。即使虛函數(shù)在類的內(nèi)部定義,但是在編譯的時(shí)候系統(tǒng)仍然將它看做是非內(nèi)聯(lián)的。5. 構(gòu)造函數(shù)不能是虛函數(shù),因?yàn)闃?gòu)造的時(shí)候,對(duì)象還是一片未定型的空間,只有構(gòu)造完成后,對(duì)象才是具體類的實(shí)例。6. 構(gòu)析函數(shù)可以是虛函數(shù),而且通常聲明為虛函數(shù)。12虛析構(gòu)函數(shù)虛析構(gòu)函數(shù)n 虛析構(gòu)函數(shù):在析構(gòu)函數(shù)前加關(guān)鍵字virtual進(jìn)行說明,則該析構(gòu)函數(shù)稱為虛析構(gòu)函數(shù);n 如果一個(gè)類的析構(gòu)函數(shù)被說明為虛析構(gòu)函數(shù),則它的派生類中的析構(gòu)函數(shù)也是虛析構(gòu)函數(shù),不管它是否使用了關(guān)鍵字virtual進(jìn)行說明n 目的:p使用delete

10、運(yùn)算符刪除一個(gè)對(duì)象時(shí),能保證析構(gòu)函數(shù)被正確地執(zhí)行;n 格式:class Bpublic: virtual B();;13純虛函數(shù)純虛函數(shù)n 引入p在基類中不能為虛函數(shù)給出一個(gè)有意義的實(shí)現(xiàn)時(shí),可將其聲明為純虛函數(shù),其實(shí)現(xiàn)留待派生類完成;n 作用p為派生類提供一個(gè)一致的接口n 聲明格式class virtual ()=0; ; 14抽象類抽象類n 定義:含有純虛函數(shù)的類稱為抽象類;n 抽象類只能作為基類使用,其純虛函數(shù)的實(shí)現(xiàn)由派生類給出;但派生類仍可不給出純虛函數(shù)的定義,繼續(xù)作為抽象類存在;n 抽象類是不能實(shí)例化的,不能生成抽象基類的對(duì)象,因此一般講該類的構(gòu)造函數(shù)說明為保護(hù)的訪問控制權(quán)限。p只能作

11、為別的類的基類。15抽象類的作用抽象類的作用n 用作基類:在一個(gè)繼承層次結(jié)構(gòu)中,提供一個(gè)公共的根,并基于抽象類的操作,設(shè)計(jì)出對(duì)抽象類所描述的一類對(duì)象進(jìn)行操作的公共接口,其完整的實(shí)現(xiàn)由派生類完成。n 用作指針或引用的基類型:保證進(jìn)入繼承層次的每個(gè)類都具有(提供)純虛函數(shù)所要求的行為。n 在成員函數(shù)內(nèi)可以調(diào)用純虛函數(shù),但在構(gòu)造函數(shù)或析構(gòu)函數(shù)內(nèi)不能調(diào)用純虛函數(shù)(純虛函數(shù)沒有實(shí)現(xiàn)代碼)class Apublic : virtual void f() = 0; void g() f(); /正確 A() f(); /錯(cuò)誤16總結(jié)總結(jié)n 對(duì)象的最基本特征是封裝和繼承n 作為一種抽象數(shù)據(jù),對(duì)象把實(shí)體的屬性(

12、相關(guān)特征)和操作封裝在一起,允許人們用自然的方式去模擬外部實(shí)體的結(jié)構(gòu)和行為。n 繼承是對(duì)象類實(shí)現(xiàn)可重用性和可擴(kuò)充性的關(guān)鍵特征。在繼承關(guān)系下對(duì)象類之間組成網(wǎng)狀的層次結(jié)構(gòu)。n 繼承也帶來了對(duì)象變量運(yùn)行時(shí)綁定的復(fù)雜性,多態(tài)性和動(dòng)態(tài)綁定使對(duì)象的類型機(jī)制實(shí)現(xiàn)更加靈活方便。17重載與重寫的概念與區(qū)別重載與重寫的概念與區(qū)別n 函數(shù)重寫(override)也稱作覆蓋:是用于類的繼承中,函數(shù)名、參數(shù)個(gè)數(shù)、類型都相同,僅函數(shù)體不同。n 函數(shù)重載(overload):是指同一作用域的不同函數(shù)使用相同的函數(shù)名,但是函數(shù)的參數(shù)個(gè)數(shù)或類型不同,簡單地講,就是不同的函數(shù)使用同一標(biāo)識(shí)符,并且這些函數(shù)位于同一作用域。n 函數(shù)隱

13、藏:既不是重載也不是重寫,例如:函數(shù)名及參數(shù)完全相同卻又不是虛函數(shù),卻在子類中重新實(shí)現(xiàn)該函數(shù),也就是所謂的隱藏。18重寫重寫/覆蓋覆蓋n 覆蓋是指派生類函數(shù)覆蓋基類函數(shù),特征是:(1)不同的范圍(分別位于派生類與基類);(2)函數(shù)名字相同;(3)參數(shù)相同;(4)基類函數(shù)必須有virtual關(guān)鍵字。 (5)重寫函數(shù)必須和原函數(shù)具有相同的返回類型。 (6)const可能會(huì)使虛成員函數(shù)的重寫失效。19函數(shù)重載函數(shù)重載 成員函數(shù)被重載的特征:(1)相同的范圍(在同一個(gè)類中);(2)函數(shù)名字相同;(3)參數(shù)不同;(4)virtual關(guān)鍵字可有可無。20函數(shù)隱藏函數(shù)隱藏n “隱藏”是指派生類的函數(shù)屏蔽了與

14、其同名的基類函數(shù),規(guī)則如下:(1)如果派生類的函數(shù)與基類的函數(shù)同名,但是參數(shù)不同。 此時(shí),不論有無virtual關(guān)鍵字,基類的函數(shù)將被隱藏(注意別與重載混淆)。(2)如果派生類的函數(shù)與基類的函數(shù)同名,并且參數(shù)也相同,但是基類函數(shù)沒有virtual關(guān)鍵字。 此時(shí),基類的函數(shù)被隱藏(注意別與覆蓋混淆)。21實(shí)例實(shí)例研究:應(yīng)用多態(tài)的工資發(fā)放系統(tǒng)研究:應(yīng)用多態(tài)的工資發(fā)放系統(tǒng)n 某家公司按周支付雇員工資。n 雇員一共有4類:p定薪雇員:不管每周工作多長時(shí)間都領(lǐng)取固定的周薪;p鐘點(diǎn)雇員:按工作的小時(shí)數(shù)領(lǐng)取工資,并且可以領(lǐng)取超過40小時(shí)以外的加班費(fèi);p傭金雇員:工資完全是銷售業(yè)績提成;p帶薪傭金雇員:工資是

15、基本工資加銷售業(yè)績提成。在這次工資發(fā)放階段,公司決定獎(jiǎng)勵(lì)帶薪傭金雇員,把他們的基本工資提高10%。公司想實(shí)現(xiàn)一個(gè)C+程序多態(tài)的執(zhí)行工資的計(jì)算。22練習(xí)練習(xí)n 構(gòu)造異質(zhì)鏈表23虛函數(shù)的實(shí)現(xiàn)機(jī)制虛函數(shù)的實(shí)現(xiàn)機(jī)制24效率的考慮效率的考慮n 面向?qū)ο笳Z言需要?jiǎng)討B(tài)綁定,即在運(yùn)行時(shí)確定具體的操作調(diào)用。因此需要在運(yùn)行時(shí)查找整個(gè)繼承樹,從而降低了效率。n 大多數(shù)語言優(yōu)化了查找的機(jī)制,通常采用方法隱藏的技術(shù),即把子類中的操作統(tǒng)一編碼存貯在表中,從而使得綁定變成了查找hash表。在C+,這個(gè)表可以存放函數(shù)的指針,使效率得到了提高。25虛函數(shù)的實(shí)現(xiàn)機(jī)制虛函數(shù)的實(shí)現(xiàn)機(jī)制n 動(dòng)態(tài)綁定又稱滯后綁定,即在編譯期并不確定函數(shù)

16、調(diào)用語句的執(zhí)行代碼,而是為它生成虛函數(shù)表用以存放同名,同參,同返回值的虛函數(shù)地址。真正的綁定推遲到程序運(yùn)行時(shí)再完成。在運(yùn)行中遇到以指針調(diào)用虛函數(shù)的語句時(shí),現(xiàn)場決定應(yīng)執(zhí)行的具體代碼。n 動(dòng)態(tài)綁定是通過虛函數(shù)表實(shí)現(xiàn)的對(duì)于含有虛函數(shù)的多態(tài),編譯器為每個(gè)對(duì)象生成一個(gè)虛表指針,即在每個(gè)對(duì)象的內(nèi)存映像中增加了一個(gè)_vfptr指針,它指向一個(gè)虛函數(shù)vtable。例如在基類的虛函數(shù)表中列出基類所有虛函數(shù)的入口地址。26虛函數(shù)的內(nèi)存映像虛函數(shù)的內(nèi)存映像27例子例子-t4.cpp-t4.cpp#include using namespace std;class Aprotected: int k;public:

17、A()k = 3; virtual int getValue()return k;class B:public A public: virtual int getValue()return k*2;void F(A *p) coutgetValue()endl;int main() A *ba = new A; B *bp = new B; coutsizeof(ba)endl; coutsizeof(*ba)endl; F(bp); return 0;輸出結(jié)果應(yīng)該是什么?28虛函數(shù)實(shí)現(xiàn)原理虛函數(shù)實(shí)現(xiàn)原理29異常處理異常處理30C C錯(cuò)誤處理機(jī)制錯(cuò)誤處理機(jī)制1. 函數(shù)返回錯(cuò)誤編碼2. 使用全局

18、變量保存錯(cuò)誤編碼3. 出錯(cuò)時(shí)終止程序運(yùn)行n 缺點(diǎn):1.難以統(tǒng)一標(biāo)準(zhǔn)2.復(fù)雜3. 構(gòu)造和析構(gòu)函數(shù)沒有返回值4. 出錯(cuò)就返回,用戶接受度低31異常處理機(jī)制異常處理機(jī)制n C+異常處理的基本思想是簡化程序的錯(cuò)誤代碼,為程序的健壯性提供了一個(gè)標(biāo)準(zhǔn)檢測機(jī)制:若底層發(fā)生問題,則逐級(jí)上報(bào),直到有能力處理此異常為止。n 異常處理的優(yōu)勢:1. 增強(qiáng)程序的健壯性。2. 使代碼變得更簡潔優(yōu)美,更易維護(hù)。3. 錯(cuò)誤信息更靈活豐富。n 缺點(diǎn):1. 性能下降5%14%。2. 破壞了程序的結(jié)構(gòu)性。3. 完成正確的異常安全的代碼,需要付出更大的代價(jià)。32拋出異常拋出異常任何時(shí)候,程序在執(zhí)行中遇到了非正常狀況都可以拋出異常異常

19、用throw語句拋出A *p = new A;if (p = NULL) throw string(“Out of Memory.”);一旦拋出異常,則程序?qū)⒃趖hrow語句處跳出33捕獲異常捕獲異常異常也由程序員負(fù)責(zé)捕獲用trycatch( )語句來捕獲異常沒有捕獲的異常將被忽略try catch(string &s) catch(double x) 34異常的傳遞異常的傳遞n 產(chǎn)生異常之后,程序會(huì)立刻跳轉(zhuǎn)p 跳出到最近的一層捕獲異常的語句p 如果當(dāng)前沒有捕獲語句或者捕獲語句中沒有匹配的異常,則程序會(huì)跳出當(dāng)前的函數(shù)n 在函數(shù)的調(diào)用處,如果沒有捕獲住異常,則直接跳轉(zhuǎn)到更高一層的調(diào)用者n

20、 如果一直沒有捕獲該異常,+將會(huì)使用默認(rèn)的異常處理函數(shù)p 該處理函數(shù)可能會(huì)讓程序最終跳出main函數(shù)并導(dǎo)致程序異常終止35捕獲任意捕獲任意異常異常-t5.cpp-t5.cpp#include using namespace std;int main( ) int a, b; a = 8; b = 4; try if (b = 0) throw Divided by Zero!; else double c = a/b; cout c endl; catch(const char *) cout Exception caught! endl; 36標(biāo)準(zhǔn)標(biāo)準(zhǔn)IOIO庫庫37標(biāo)準(zhǔn)標(biāo)準(zhǔn)IOIO頭文件頭

21、文件類型類型iostreamistream 從流中讀取ostream寫到流中去iostream對(duì)流進(jìn)行讀寫;從istream和ostream派生fstreamifstream從文件中讀取,由istream派生而來ofstream寫到文件中去;由ostream派生而來fstream讀寫文件;由iostream派生而來sstreamistringstream從string對(duì)象中讀取;由istream派生而來ostringstream寫到string對(duì)象中去;由ostream派生而來stringstrem對(duì)string對(duì)象進(jìn)行讀寫;由iostream派生而來參考:C+ Primer中文版第8章標(biāo)準(zhǔn)I

22、O庫38IOIO類型特性類型特性n IO類中對(duì)國際字符的支持 標(biāo)準(zhǔn)庫中還定義了一組相關(guān)的類型,支持wchar_t類型. 在每個(gè)類都加上“w” 前綴,以此與char類型的版本區(qū)分開來IO對(duì)象不可復(fù)制和賦值 ofstream out1, out2; out1 = out2; /錯(cuò)誤 形參或返回類型也不能為流類型。如果需要傳遞或返回IO對(duì)象,則必須傳遞或返回該對(duì)象的指針或引用。39流的概念及用途流的概念及用途n C+的I/O是以字節(jié)流的形式實(shí)現(xiàn)的,流(stream)實(shí)際上就是一個(gè)字節(jié)序列。n輸入流:在輸入操作中,字節(jié)從輸入設(shè)備(如鍵盤、磁盤、網(wǎng)絡(luò)連接等)流向內(nèi)存;n輸出流:在輸出操作中,字節(jié)從內(nèi)存流

23、向輸出設(shè)備(如顯示器、打印機(jī)、磁盤、網(wǎng)絡(luò)連接等);n 應(yīng)用程序把字節(jié)的含義與字節(jié)關(guān)聯(lián)起來。n 輸人/輸出系統(tǒng)的任務(wù)實(shí)際上就是以一種穩(wěn)定、可靠的方式在設(shè)備與內(nèi)存之間傳輸數(shù)據(jù)。40有關(guān)流的頭文件有關(guān)流的頭文件n iostream:包含了操作所有輸入/輸出流所需的基本信息,因此大多數(shù)C+程序都必須包含它。n iomanip:如果用到了含參數(shù)的流操縱算子,則必須包含它,如需使用setfill, setw, setbase, setprecision等。n fstream:包含了文件操作所需的基本信息。當(dāng)程序用到文件時(shí),必須包含它。41輸入輸出流類輸入輸出流類iosistreamostreamifstr

24、eamofstreamiostreamfstream42標(biāo)準(zhǔn)流標(biāo)準(zhǔn)流n cin是類istream的對(duì)象,它與標(biāo)準(zhǔn)輸入設(shè)備(通常指鍵盤)連在一起。n cout是類ostream的對(duì)象,它與標(biāo)準(zhǔn)輸出設(shè)備(通常指顯示設(shè)備)連在一起。n cerr是類osteam的對(duì)象,它與標(biāo)準(zhǔn)錯(cuò)誤輸出設(shè)備連在一起,對(duì)象cerr的輸出是無緩沖的。 n clog是類ostream的對(duì)象,它與標(biāo)準(zhǔn)錯(cuò)誤輸出設(shè)備連在一起,對(duì)象clog的輸出是有緩沖的。43流的概念及用途流的概念及用途n I/O操作是以對(duì)數(shù)據(jù)類型敏感的方式執(zhí)行的。C+的I/O操作是以字節(jié)流的形式實(shí)現(xiàn)的。流實(shí)際上就是字節(jié)序列。n C+提供了低級(jí)和高級(jí)I/O功能。低

25、級(jí)I/O功能通常只在設(shè)備和內(nèi)存之間傳輸一些字節(jié)。高級(jí)I/O功能把若干個(gè)字節(jié)組合成有意義的單位,如整數(shù)、浮點(diǎn)數(shù)、字符、字符串以及用戶自定義類型的數(shù)據(jù)。n C+提供了無格式I/O和格式化I/O兩種操作。無格式I/O傳輸速度快,但使用起來較為麻煩。格式化I/O按不同的類型對(duì)數(shù)據(jù)進(jìn)行處理,但需要增加額外的處理時(shí)間,不適于處理大容量的數(shù)據(jù)傳輸。 44輸出流輸出流n C+的類ostream提供了格式化輸出和無格式輸出的功能 n 輸出功能包括p用流插入運(yùn)算符輸出標(biāo)準(zhǔn)類型的數(shù)據(jù);p用成員函數(shù)put輸出字符;p成員函數(shù)write的無格式化輸出;p輸出特定形式數(shù)值45流插入運(yùn)算符流插入運(yùn)算符n 輸出標(biāo)準(zhǔn)類型的數(shù)據(jù)

26、。n 格式: cout 數(shù)據(jù)項(xiàng) ;n eg. #include using namespace std;int main() cout Welcome to C+!n; return 0;輸出結(jié)果:Welcome to C+!流插入運(yùn)算符46輸出流輸出流輸出char*類型的變量#include using namespace std;int main()const char *string = test;cout Value of string is: string nValue of static_cast( string ) is: static_cast( string ) endl;r

27、eturn 0;輸出結(jié)果:Value of string is: testValue of static_cast( string ) is:0 x80488a0返回char*類型的字符串 返回字符串中第一個(gè)字符的地址 輸出的地址是用十六進(jìn)制格式表示 47用成員用成員函數(shù)函數(shù)putput輸出字符輸出字符n cout.put(A); 將字符A顯示在屏幕上。 連續(xù)調(diào)用put函數(shù): cout.put(A).put(n); 該語句在輸出字符A后輸出一個(gè)換行符。圓點(diǎn)運(yùn)算符(.)從左向右結(jié)合,put 成員函數(shù)返回調(diào)用put的對(duì)象的引用。n cout.put(65);用ASCII碼值表達(dá)式調(diào)用put函數(shù),語

28、句也輸出字符A。48writewrite的無格式輸出的無格式輸出n 調(diào)用成員函數(shù)write可實(shí)現(xiàn)無格式輸出。這個(gè)函數(shù)把一定量的字節(jié)從字符數(shù)組中輸出。這些字節(jié)都是未經(jīng)任何格式化的,僅僅是以原始數(shù)據(jù)形式輸出。例如: char buffer = HAPPY BIRTHDAY; cout.write(buffer,10); 輸出buffet的10個(gè)字節(jié)n 函數(shù)調(diào)用:cout.write(ABCDEFGHIJKLMNOPQRSTUVWXYZ,10); 顯示了字母表中的前10個(gè)字母。 49輸入流輸入流n 流讀取運(yùn)算符 n get函數(shù)n getline函數(shù)n 其他函數(shù)50流讀取運(yùn)算符流讀取運(yùn)算符n 流的輸入

29、最常用的是流讀取運(yùn)算符。n 流讀取運(yùn)算符通常會(huì)跳過輸人流中的空格、tab鍵、換行符等空白字符。n 當(dāng)遇到輸入流中的文件結(jié)束符時(shí),流讀取運(yùn)算符返回0(false);否則,流讀取運(yùn)算符返回對(duì)調(diào)用該運(yùn)算符的對(duì)象的引用。51實(shí)例實(shí)例n 查找某次考試的最高成績。假定事先不知道有多少個(gè)考試成績,并且用戶會(huì)輸入表示成績輸入完畢的文件結(jié)束符。當(dāng)用戶輸入文件結(jié)束符時(shí),while循環(huán)結(jié)構(gòu)中的條件(cingrade)將變?yōu)?(即false)。52#include using namespace std;int main() int grade, highestGrade = -1; cout grade) if (

30、 grade highestGrade )highestGrade = grade;cout Enter grade (enter end-of-file to end): ;cout nnHighest grade is: highestGrade endl; return 0;輸出結(jié)果:Enter grade (enter end-of-file to end): 67Enter grade (enter end-of-file to end): 87Enter grade (enter end of file to end): 73Enter grade (enter end-of-fi

31、le to end): 95Enter grade (enter end-of-file to end): 34Enter grade (enter end-of-file to end): 99Entergrade (enter end-of-file to end): zHeighest grade is: 9953成員函數(shù)成員函數(shù)getgetn 不帶參數(shù)的get函數(shù)從指定的輸入流中讀取(輸入)一個(gè)字符(包括空白字符),并返回該字符作為函數(shù)調(diào)用的值;n 當(dāng)遇到輸入流中的文件結(jié)束符時(shí),該版本的get函數(shù)返回EOF。 54#include using namespace std;int mai

32、n() char c; cout Before input, cin.eof() is cin.eof() nEnter a sentence followed by end-of-file:n; while (!cin.eof() c = cin.get(); cout.put( c ); cout nEOF in this system is: (int)c; cout nAfter input, cin.eof() is cin.eof() endl; return 0;55帶一個(gè)字符型參數(shù)的帶一個(gè)字符型參數(shù)的getget成員函數(shù)成員函數(shù)自動(dòng)讀取輸人流中的下一個(gè)字符。例: char c1

33、,c2,c3; cin.get(c1); cin.get(c2); cin.get(c3);若輸入:AB CD則:c1=A,c2=B,c3=n56 例子例子例:讀取當(dāng)前行的剩余字符,但不對(duì)它們作任何處理 void new_line( ) char symbol; do cin.get(symbol); while (symbol !=n); 57帶有三個(gè)參數(shù)的帶有三個(gè)參數(shù)的getget成員函數(shù)成員函數(shù)n 參數(shù)分別是接收字符的字符數(shù)組、字符數(shù)組的大小和分隔符(默認(rèn)值為n)。n 函數(shù)或者在讀取比指定的最大字符數(shù)少一個(gè)字符后結(jié)束,或者在遇到分隔符時(shí)結(jié)束。n 為使字符數(shù)組(被程序用作緩沖區(qū))中的輸入字

34、符串能夠結(jié)束,函數(shù)不把分隔符放到字符數(shù)組中,但是分隔符仍然會(huì)保留在輸入流中。因此第二次get函數(shù)調(diào)用所得的結(jié)果將是個(gè)空行,除非講結(jié)束符從輸入流中移除(可以使用cin.ignore())。58#include using namespace std;int main() const int SIZE = 80; char buffer1 SIZE ; char buffer2 SIZE ; cout Enter a sentence: buffer1; /cin.get(buffer1,SIZE, ); /cin.ignore(); cout nThe string read with cin

35、was: endl buffer1 endl endl; cin.get( buffer2, SIZE ); cout The string read with cin.get was: endl buffer2 endl; return 0;例子例子59成員函數(shù)成員函數(shù)getlinegetlinen 與帶三個(gè)參數(shù)的get函數(shù)類似,它讀取一行信息到字符數(shù)組中,然后插入一個(gè)空字符。n 所不同的是,getline要去除輸入流中的分隔符(即讀取字符并刪除它),但是不把它存放在字符數(shù)組中。60#include using namespace std;int main() const int SIZE

36、= 80; char buffer SIZE ; cout Enter a sentence: endl; cin.getline( buffer, SIZE ); cout nThe sentence entered is: endl buffer endl; return 0;61istreamistream類中的其他成員函數(shù)類中的其他成員函數(shù)n ignore用于在需要時(shí)跳過流中指定數(shù)量的字符(默認(rèn)個(gè)數(shù)是1),或在遇到指定的分隔符(默認(rèn)分隔符是EOF,使得ignore在讀文件的時(shí)候跳過文件末尾)時(shí)結(jié)束。n putback將最后一次用get從輸人流中提取的字符放回到輸入流中。n peek返回

37、輸入流中的下一個(gè)字符,但并不將其從輸入流中刪除。 62istreamistream類中的其他成員函數(shù)類中的其他成員函數(shù)n 成員函數(shù)read無格式輸入n gcount統(tǒng)計(jì)最后輸入的字符個(gè)數(shù)63#include using namespace std;int main() const int SIZE = 80; char buffer SIZE ; cout Enter a sentence: endl; cin.read( buffer, 20 ); cout endl The sentence entered was: endl; cout.write( buffer, cin.gcount

38、() ); cout endl; return 0;例子例子輸出結(jié)果:Enter a sentence:Using the read, write, and gcount member functionsThe sentence entered was:Using the read,write64格式化輸入格式化輸入/ /輸出輸出n C+提供了大量的用于執(zhí)行格式化輸入/輸出的流操縱符和成員函數(shù)。n 功能: 整數(shù)流的基數(shù):dec、oct、hex和setbase() 設(shè)置浮點(diǎn)數(shù)精度:precision、setprecision() 設(shè)置域?qū)?setw、width() 設(shè)置域填充字符:fill、se

39、tfill()65hexhex、octoct、decdec和和setbasesetbase#include #include using namespace std;int main() int number; cout number; cout number in hexadecimal is: hex number endl; cout dec number in octal is: oct number endl; cout setbase(10) number in decimal is: number endl; return 0;輸出結(jié)果:Enter a decimalnumber

40、: 2020 in hexadecimal is:1420 in octal is: 2420 in decimal is: 20 66浮點(diǎn)精度(浮點(diǎn)精度(precisionprecision,setprecisionsetprecision)#include #include #include using namespace std;int main() double root2 = sqrt( 2.0 ); int places;/ use fixed point format cout fixed; for ( places = 0; places = 9; places+ ) cout

41、.precision( places ); cout root2 endl; for ( places = 0; places = 9; places+ ) cout setprecision( places ) root2 endl; return 0;67域域?qū)挘▽挘╳idthwidth,setwsetw)#include #include using namespace std;int main() int widthValue = 4; char sentence 10 ; cout Enter a sentence: sentence ) cout.width( widthValue

42、+ ); cout sentence endl; / coutsetw(widthValue+) sentence endl; cin.width( 5 ); return 0;68用戶自定義的流操縱算子用戶自定義的流操縱算子#include using namespace std;ostream& bell( ostream& output ) return output a; / issue system beep ostream& carriageReturn( ostream& output ) return output r; / issue carr

43、iage return ostream& tab( ostream& output ) return output t; / issue tab ostream& endLine( ostream& output ) return output n flush; / issue endl-like end of line 69輸出結(jié)果:int main() cout Testing the tab manipulator: endLine a tab b tab c endLine; cout Testing the carriageReturn and bel

44、l manipulators: endLine .; cout bell; / use bell manipulator cout carriageReturn - endLine; return 0; 70小結(jié)小結(jié) C+的I/O操作是以字節(jié)流的形式實(shí)現(xiàn)的。流實(shí)際上就是字節(jié)序列。輸入/輸出系統(tǒng)的任務(wù)實(shí)際上就是以一種穩(wěn)定、可靠的方式在設(shè)備與內(nèi)存之間傳輸數(shù)據(jù)。C+提供了低級(jí)和高級(jí)I/O功能。低級(jí)I/O功能通常只在設(shè)備和內(nèi)存之間傳輸一些字節(jié)。高級(jí)I/O功能把若干個(gè)字節(jié)組合成有意義的單位。71小結(jié)小結(jié)C+提供了無格式I/O和格式化I/O兩種操作。頭文件iostream包括了操作所有輸入/輸出流所需的基

45、本信息,因此在大多數(shù)C+程序中都應(yīng)該包含這個(gè)頭文件。在執(zhí)行格式化I/O時(shí),如果流中帶有含參數(shù)的流操縱算子,頭文件iomanip所包含的信息是有用的。72小結(jié)小結(jié)頭文件fstream包含了文件處理操作所需的信息。類istream支持流的輸入操作。類ostream支持流的輸出操作。類iostream同時(shí)支持流的輸入、輸出操做。類istream和ostream是通過單一繼承從基類ios派生出來的。類iostream是通過多重繼承從類istream和ostream派生出來的。73小結(jié)小結(jié)重載的左移位運(yùn)算符()表示流的輸入,稱為流讀取運(yùn)算符。cin是類istream的對(duì)象,它與標(biāo)準(zhǔn)輸入設(shè)備(通常指鍵盤)

46、“連”在一起。cout是類ostream的對(duì)象,它與標(biāo)準(zhǔn)輸出設(shè)備(通常指顯示器)“連”在一起。74小結(jié)小結(jié)流操縱算子endl用來插入一個(gè)換行符,并同時(shí)刷新輸出緩沖區(qū)。C+編譯器能夠自動(dòng)識(shí)別輸入、輸出數(shù)據(jù)的類型。我們通常在while循環(huán)結(jié)構(gòu)的首部用流讀取運(yùn)算符輸入一系列值。當(dāng)遇到文件結(jié)束符時(shí),流讀取運(yùn)算符返回0。75小結(jié)小結(jié)不帶參數(shù)的get函數(shù)讀取(輸入)一個(gè)字符,并返回該字符;帶一個(gè)字符型參數(shù)的get成員函數(shù)輸入一個(gè)字符。帶有三個(gè)參數(shù)的get成員函數(shù),其三個(gè)參數(shù)分別是接收字符的字符數(shù)組、字符數(shù)組的大小和分隔符(默認(rèn)值為n)。76文件文件77文件文件n 臨時(shí)數(shù)據(jù)p存儲(chǔ)在變量和數(shù)組中的數(shù)據(jù)是臨時(shí)的

47、,這些數(shù)據(jù)在程序運(yùn)行結(jié)束后都會(huì)消失。 n 文件p目的:文件用來永久地保存大量的數(shù)據(jù)。p存儲(chǔ):計(jì)算機(jī)把文件存儲(chǔ)在二級(jí)存儲(chǔ)設(shè)備中(特別是磁盤存儲(chǔ)設(shè)備)。 78文件中的數(shù)據(jù)層次文件中的數(shù)據(jù)層次n 位(bit): 最小數(shù)據(jù)項(xiàng):0和1n 字符(character)/字節(jié)(byte)字符:數(shù)字、字母和專門的符號(hào)字節(jié):0、1序列 (常見的是8位/字節(jié))字符用字節(jié)表示n 域(field):一組有意義的字符n 記錄(record)p 一組相關(guān)的域p 記錄關(guān)鍵字(record key):用于檢索n 文件(file):一組相關(guān)的記錄n 數(shù)據(jù)庫:一組相關(guān)的文件79文件中記錄的組織方式文件中記錄的組織方式 n 文件中記

48、錄常見的兩種組織方式p順序訪問文件(sequential access file) : 按記錄關(guān)鍵字字段的順序存儲(chǔ)記錄的文件。 例:在工資表文件中記錄通常按雇員標(biāo)識(shí)號(hào)的順序存儲(chǔ)與訪問。 p隨機(jī)訪問文件(random access file) 按隨機(jī)順序訪問與存儲(chǔ)記錄的文件。80文件和流文件和流n C+語言把每一個(gè)文件都看成一個(gè)有序的字節(jié)流(把文件看成n個(gè)字節(jié)) p每一個(gè)文件或者以文件結(jié)束符(end-of-file marker)結(jié)束,或者在特定的字節(jié)號(hào)處結(jié)束p當(dāng)打開一個(gè)文件時(shí),該文件就和某個(gè)流關(guān)聯(lián)起來p與這些對(duì)象相關(guān)聯(lián)的流提供程序與特定文件或設(shè)備之間的通信通道 例如cin對(duì)象(標(biāo)準(zhǔn)輸入流對(duì)象)

49、使程序能從鍵盤輸入數(shù)據(jù),cout對(duì)象(標(biāo)準(zhǔn)輸出流對(duì)象)使程序能向屏幕輸出數(shù)據(jù),cerr和clog對(duì)象(標(biāo)準(zhǔn)錯(cuò)誤流對(duì)象)使程序能向屏幕輸出錯(cuò)誤消息。 81ifstream, fstream, ofstreamifstream, fstream, ofstreamn 要在C+中進(jìn)行文件處理,就要包括頭文件和。p頭文件包括流類ifstream(從文件輸入)、ofstream(向文件輸出)和fstream(從文件輸入,輸出)的定義。生成這些流類的對(duì)象即可打開文件。82建立順序訪問文件建立順序訪問文件 n C+把文件看作是無結(jié)構(gòu)的字節(jié)流 n 記錄的說法在C+文件中是不存在的。程序員必須提供滿足特定應(yīng)用程

50、序要求的文件結(jié)構(gòu)。n 問題:怎樣給文件強(qiáng)加一個(gè)記錄結(jié)構(gòu) ? 83例子例子file_out.cppfile_out.cpp#include #include / file stream#include using namespace std;int main() ofstream outClientFile( clients.dat, ios:out ); / exit program if unable to create file if ( !outClientFile ) / overloaded ! operator cerr File could not be opened endl;

51、 exit( 1 ); cout Enter the account, name, and balance. endl account name balance ) outClientFile account name balance endl; cout account name balance )只要cin的failbit和badbit都沒有設(shè)置,則條件保持true。輸入文件結(jié)束符設(shè)置cin的failbit。operator void*函數(shù)可以測試輸入對(duì)象的文件結(jié)束符,而不必對(duì)輸入對(duì)象顯式調(diào)用eof成員函數(shù)。90打開輸入文件打開輸入文件n ifstream inClientFile( “c

52、lients.dat”, ios:in ); p 生成ifstream對(duì)象inClientFile,并將其與打開以便輸入的文件clients.dat相關(guān)聯(lián)。括號(hào)中的參數(shù)傳入ifstream構(gòu)造函數(shù),打開文件并建立與文件的通信線路。p 打開ifstream類對(duì)象默認(rèn)為進(jìn)行輸入,因此下列語句等價(jià): ifstream inClientFile( “Clients.dat” );p 和ofstream對(duì)象一樣,ifstream對(duì)象也可以生成而不打開特定文件,然后再將用open對(duì)象與文件相連接。 91例子例子見代碼file_in.cpp92文件位置指針文件位置指針n 為了按順序檢索文件中的數(shù)據(jù),程序通常

53、要從文件的起始位置開始讀取數(shù)據(jù),然后連續(xù)地讀取所有的數(shù)據(jù),直到找到所需要的數(shù)據(jù)為止??赡苄枰磸?fù)多次。n 文件位置指針( file position pointer):用于指示讀寫操作所在的下一個(gè)字節(jié)號(hào);是個(gè)整數(shù)值,指定文件中離文件開頭的相對(duì)位置(也稱為離文件開頭的偏移量),93文件指針重新定位文件指針重新定位n istream類和ostream類都提供成員函數(shù),使文件位置指針重新定位p istream類的seekg (即“seekget”) :每個(gè)istream對(duì)象有個(gè)get指針,表示文件中下一個(gè)輸入相距的字節(jié)數(shù)p ostream類的seekp (即“seekput”):每個(gè)ostream對(duì)

54、象有一個(gè)put指針,表示文件中下一個(gè)輸出相距的字節(jié)數(shù)n seekg和seekp的第一個(gè)參數(shù)通常為long類型的整數(shù),表示偏移量。第二個(gè)參數(shù)可以指定尋找方向: ios:beg(默認(rèn))相對(duì)于流的開頭定位 ios:cur相對(duì)于流當(dāng)前位置定位 ios:end相對(duì)于流結(jié)尾定位94文件位置指針的例子文件位置指針的例子 / position to the nth byte of fileObject / assumes ios:beg fileObject.seekg( n ); / position n bytes forward in fileObject fileObject.seekg( n, io

55、s:cur ); / position y bytes back from end of fileObject fileObject.seekg( y, ios:end ); / position at end of fileObject fileObject.seekg( 0, ios:end );95獲取文件指針值獲取文件指針值n 成員函數(shù)tellg和tellp分別返回get和put指針的當(dāng)前位置。下列語句將get文件位置指針值賦給long類型的變量location。 location = filObject.tellg();96更新順序訪問文件更新順序訪問文件n 格式化和寫入順序訪問文件

56、的數(shù)據(jù)修改時(shí)會(huì)有破壞文件中其他數(shù)據(jù)的危險(xiǎn) n 例如,如果要把名字“White”改為“Worthington”,則不是簡單地重定義舊的名字。White的記錄是以如下形式寫入文件中的: 300 White 0.00 如果用新的名字從文件中相同的起始位置重寫該記錄,記錄的格式就成為: 300 Worthington 0.00因?yàn)樾碌挠涗涢L度大于原始記錄的長度,所以從“Worthington”的第二個(gè)“o”之后的字符將重定義文件中的下一條順序記錄。n 出現(xiàn)該問題的原因在于:在使用流插入運(yùn)算符的格式化輸入,輸出模型中,域的大小是不定的,因而記錄的大小也是不定的。例如,7、14、-117、2047和273

57、83都是int類型的值,雖然它們的內(nèi)部存儲(chǔ)占用相同的字節(jié)數(shù),因此,格式化輸入輸出模型通常不用來更新已有的記錄。97更新順序訪問文件(續(xù))更新順序訪問文件(續(xù))n 一種解決方法:將在300 White 0.00之前的記錄復(fù)制到一個(gè)新的文件中,然后寫入新的記錄并把300 White 0.00之后的記錄復(fù)制到新文件中。這種方法要求在更新一條記錄時(shí)處理文件中的每一條記錄。如果文件中一次要更新許多記錄,則可以用這種方法。98運(yùn)算符重載運(yùn)算符重載99運(yùn)算符重載運(yùn)算符重載n 運(yùn)算符重載就是賦予已有的運(yùn)算符多重含義。n C+中通過重新定義運(yùn)算符,使它能夠用于特定類的對(duì)象執(zhí)行特定的功能,這便增強(qiáng)了C+語言的擴(kuò)充

58、能力。100運(yùn)算符重載的注意事項(xiàng)運(yùn)算符重載的注意事項(xiàng)n 不能重載的運(yùn)算符名 : .* . ? :n 重載運(yùn)算符必須具有一個(gè)類類型(或枚舉類型)操作數(shù)n 優(yōu)先級(jí)和結(jié)合性是固定的 x = y + z;n 不再具有短路求值特性 重載運(yùn)算符并不保證操作數(shù)的求值順序, 尤其是邏輯運(yùn)算和逗號(hào)操作符。重載&、|、或逗號(hào) 運(yùn)算符不是好的做法。101類成員與非類成員類成員與非類成員n 大多數(shù)的重載運(yùn)算符可以定義為普通非成員函數(shù)或類的成員函數(shù)。 作為類成員的重載函數(shù),其形參看起來比操作數(shù)數(shù)目少1。 String& operator =(const String &rhs); String&

59、amp; String:operator = (const String &rhs)n 一般講算術(shù)和關(guān)系操作符定義為非成員函數(shù), 而將賦值操作符定義為成員;n 當(dāng)操作符為成員函數(shù)時(shí), this指針指向左操作數(shù), 因此,非成員operator+定義兩個(gè)形參。102操作符重載和友元的關(guān)系操作符重載和友元的關(guān)系n 操作符定義為非成員函數(shù)時(shí), 通常必須將它們?cè)O(shè)置為所操作類的友元。因?yàn)樵谶@種情況下,操作符通常需要訪問類的私有部分。103重載運(yùn)算符的使用重載運(yùn)算符的使用1. 可以像使用內(nèi)置類型操作符一樣使用 cout a+b endl;2. 可以像調(diào)用普通函數(shù)一樣調(diào)用重載運(yùn)算符, 指定函數(shù)并傳遞適

60、當(dāng)類型適當(dāng)數(shù)目的參數(shù)。 cout operator+(a, b) endl;104重載運(yùn)算符的設(shè)計(jì)重載運(yùn)算符的設(shè)計(jì)n 不要重載具有內(nèi)置含義的操作符 (& , & , |) 重載的賦值運(yùn)算應(yīng)當(dāng)在賦值的內(nèi)置含義基礎(chǔ)上進(jìn)行定制,而不是完全繞開。n 大多數(shù)操作符對(duì)類對(duì)象沒有意義 根據(jù)需要將某些運(yùn)算符重載n 復(fù)合賦值運(yùn)算符 =, +=n 相等和關(guān)系運(yùn)算符( = !=)n 選擇成員或非成員實(shí)現(xiàn) 1. = () -等必須定義為成員(+=不是必須) 2. 改變對(duì)象狀態(tài)或與給定類型密切聯(lián)系的其他運(yùn)算符,如自增、自減,應(yīng)定義為類成員 3. 對(duì)稱的操作符,如算術(shù)運(yùn)算、關(guān)系操作符、位操作符。最好定義為普通非成員函數(shù)。警告: 不要濫用運(yùn)算符重載105單目運(yùn)算符的重載單目運(yùn)算符的重載1 1n operator +作為友員的重載class A friend A& operator + (A&);int a,b;public:A(int x

溫馨提示

  • 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)論