簡介:第四章UNIX下的C語言開發(fā)環(huán)境,,61程序設(shè)計(jì)環(huán)境,學(xué)習(xí)程序設(shè)計(jì)從程序語言開始,但還應(yīng)了解程序執(zhí)行和程序與外界的交互問題。,1理想態(tài)的程序運(yùn)行環(huán)境,,用戶程序直接控制和使用各種設(shè)備,完成各種操作。,針對一個簡單程序,MAIN{INTCWHILECGETCHAREOFPUTCHARC},,認(rèn)為執(zhí)行過程為,在單用戶單任務(wù)環(huán)境中基本符合。,2多任務(wù)環(huán)境下程序執(zhí)行,多任務(wù)中每一時刻都會有多個用戶程序提出訪問請求,因此會有,,如此混亂的情況,程序?qū)o法運(yùn)行。,為使多道環(huán)境中的程序正確執(zhí)行,需要OS管理。,,用戶程序需要系統(tǒng)核心區(qū)程序的管理,達(dá)到各自任務(wù)的執(zhí)行。,62基于系統(tǒng)支持的程序設(shè)計(jì),,1建立系統(tǒng)編程的思想,理解多道環(huán)境程序執(zhí)行狀況,轉(zhuǎn)換用戶程序是執(zhí)行主體的認(rèn)識。了解OS可提供的服務(wù)及服務(wù)方式。充分利用OS提供服務(wù)功能解決實(shí)際問題。盡量使編寫的程序最大限度的滿足系統(tǒng)平臺的支持能力。,1GCC與GDB,11UNIX和C語言C是一種在UNIX操作系統(tǒng)的早期就被廣泛使用的通用編程語言,它最早是由貝爾實(shí)驗(yàn)室的DENNISRITCHIE為了UNIX的輔助開發(fā)而寫的。C是所有版本的UNIX上的系統(tǒng)語言。幾乎任何一種計(jì)算機(jī)上都有至少一種能用的C編譯器;并且它的語法和函數(shù)庫在不同的平臺上都是統(tǒng)一的。80年代末期美國國家標(biāo)準(zhǔn)協(xié)會AMERICANNATIONALSTANDARDSINSTITUTE發(fā)布了一個被稱為ANSIC的C語言標(biāo)準(zhǔn),這保證了在不同平臺上的C的一致性。,7,1GCC與GDB,12GNUC編譯器GNUC編譯器GCC是一個全功能的ANSIC兼容編譯器,它是所有UNIX系統(tǒng)可用的C編譯器。GCC是可以在多種硬體平臺上編譯出可執(zhí)行程序的超級編譯器,其執(zhí)行效率與一般的編譯器相比平均效率要高2030。,8,31LINUX下C語言編程概述,1GCC與GDB,GCC編譯過程預(yù)處理,對源代碼文件中的文件包含INCLUDE、預(yù)編譯語句如宏定義DEFINE等進(jìn)行分析。編譯,就是把C/C代碼“翻譯”成匯編代碼。匯編,將第二步輸出的匯編代碼翻譯成符合一定格式的機(jī)器代碼,生成以O(shè)為后綴的目標(biāo)文件。鏈接,將上步生成的目標(biāo)文件和系統(tǒng)庫的目標(biāo)文件和庫文件鏈接起來,最終生成了可以在特定平臺運(yùn)行的可執(zhí)行文件。,10,1GCC編譯流程解析如本章開頭提到的,GCC的編譯流程分為了4個步驟,分別為預(yù)處理(PREPROCESSING);編譯(COMPILING);匯編(ASSEMBLING);鏈接(LINKING)。下面就具體來查看一下GCC是如何完成4個步驟的。首先,有以下HELLOC源代碼INCLUDEINTMAIN{PRINTF“HELLOTHISISOUREMBEDDEDWORLD\N“RETURN0},33GCC編譯器,(1)預(yù)處理階段在該階段,編譯器將上述代碼中的STDIOH編譯進(jìn)來,并且用戶可以使用GCC的選項(xiàng)“E”進(jìn)行查看,該選項(xiàng)的作用是讓GCC在預(yù)處理結(jié)束后停止編譯過程。ROOTLOCALHOSTGCCGCC–EHELLOC–OHELLOI在此處,選項(xiàng)“O”是指目標(biāo)文件,由上表可知,“I”文件為已經(jīng)過預(yù)處理的C原始程序。以下列出了HELLOI文件的部分內(nèi)容TYPEDEFINT__GCONV_TRANS_FCTSTRUCT__GCONV_STEP,STRUCT__GCONV_STEP_DATA,VOID,__CONSTUNSIGNEDCHAR,__CONSTUNSIGNEDCHAR,__CONSTUNSIGNEDCHAR,UNSIGNEDCHAR,SIZE_T,,2“HELLOC“2INTMAIN{PRINTF“HELLOTHISISOUREMBEDDEDWORLD\N“RETURN0}由此可見,GCC確實(shí)進(jìn)行了預(yù)處理,它把“STDIOH”的內(nèi)容插入到HELLOI文件中。,(2)編譯階段接下來進(jìn)行的是編譯階段,在這個階段中,GCC首先要檢查代碼的規(guī)范性、是否有語法錯誤等,以確定代碼的實(shí)際要做的工作,在檢查無誤后,GCC把代碼翻譯成匯編語言。用戶可以使用“S”選項(xiàng)來進(jìn)行查看,該選項(xiàng)只進(jìn)行編譯而不進(jìn)行匯編,生成匯編代碼。ROOTLOCALHOSTGCCGCC–SHELLOI–OHELLOS以下列出了HELLOS的內(nèi)容,可見GCC已經(jīng)將其轉(zhuǎn)化為匯編了,感興趣的讀者可以分析一下這一行簡單的C語言小程序是如何用匯編代碼實(shí)現(xiàn)的。FILE“HELLOC“SECTIONRODATAALIGN4LC0STRING“HELLOTHISISOUREMBEDDEDWORLD“TEXTGLOBLMAINTYPEMAIN,FUNCTIONMAINPUSHL?PMOVLESP,?PSUBL8,ESPANDL16,ESPMOVL0,?XADDL15,?XSECTIONNOTEGNUSTACK,““,PROGBITS,(3)匯編階段匯編階段是把編譯階段生成的“S”文件轉(zhuǎn)成目標(biāo)文件,讀者在此可使用選項(xiàng)“C”就可看到匯編代碼已轉(zhuǎn)化為“O”的二進(jìn)制目標(biāo)代碼了。如下所示ROOTLOCALHOSTGCCGCC–CHELLOS–OHELLOO,GCC編譯器,(4)鏈接階段在成功編譯之后,就進(jìn)入了鏈接階段。在這里涉及到一個重要的概念函數(shù)庫。讀者可以重新查看這個小程序,在這個程序中并沒有定義“PRINTF”的函數(shù)實(shí)現(xiàn),且在預(yù)編譯中包含進(jìn)的“STDIOH”中也只有該函數(shù)的聲明,而沒有定義函數(shù)的實(shí)現(xiàn),那么,是在哪里實(shí)現(xiàn)“PRINTF”函數(shù)的呢最后的答案是系統(tǒng)把這些函數(shù)實(shí)現(xiàn)都被做到名為LIBCSO6的庫文件中去了,在沒有特別指定時,GCC會到系統(tǒng)默認(rèn)的搜索路徑“/USR/LIB”下進(jìn)行查找,也就是鏈接到LIBCSO6庫函數(shù)中去,這樣就能實(shí)現(xiàn)函數(shù)“PRINTF”了,而這也就是鏈接的作用。函數(shù)庫一般分為靜態(tài)庫和動態(tài)庫兩種。靜態(tài)庫是指編譯鏈接時,把庫文件的代碼全部加入到可執(zhí)行文件中,因此生成的文件比較大,但在運(yùn)行時也就不再需要庫文件了。其后綴名一般為“A”。動態(tài)庫與之相反,在編譯鏈接時并沒有把庫文件的代碼加入到可執(zhí)行文件中,而是在程序執(zhí)行時由運(yùn)行時鏈接文件加載庫,這樣可以節(jié)省系統(tǒng)的開銷。動態(tài)庫一般后綴名為“SO”,如前面所述的LIBCSO6就是動態(tài)庫。GCC在編譯時默認(rèn)使用動態(tài)庫。完成了鏈接之后,GCC就可以生成可執(zhí)行文件,如下所示。ROOTLOCALHOSTGCCGCCHELLOO–OHELLO運(yùn)行該可執(zhí)行文件,出現(xiàn)正確的結(jié)果如下。ROOTLOCALHOSTGCC/HELLOHELLOTHISISOUREMBEDDEDWORLD,GCC編譯選項(xiàng),GCC編譯器,1UNIX下的C語言開發(fā)環(huán)境,GCC遵循的文件類型規(guī)定C為后綴的文件,C語言源代碼文件;A為后綴的文件,是由目標(biāo)文件構(gòu)成的檔案庫文件;C,CC或CXX為后綴的文件,是C源代碼文件;H為后綴的文件,是程序所包含的頭文件;I為后綴的文件,是已經(jīng)預(yù)處理過的C源代碼文件;II為后綴的文件,是已經(jīng)預(yù)處理過的C源代碼文件;M為后綴的文件,是OBJECTIVEC源代碼文件;O為后綴的文件,是編譯后的目標(biāo)文件;S為后綴的文件,是匯編語言源代碼文件;S為后綴的文件,是經(jīng)過預(yù)編譯的匯編語言源代碼文件。,18,頭文件,頭文件是用來提供常量的定義和系統(tǒng)和函數(shù)調(diào)用的聲明,這些頭文件通常放在/USR/INCLUDE和其子目錄中。根據(jù)不同的LINUX版本,頭文件可能放在/USR/INCLUDE/SYS和/USR/INCLUDE/LINUXINCLUDE,庫函數(shù),庫函數(shù)是一些預(yù)先編譯好的函數(shù)的集合,這些函數(shù)可以有很好的重用性。通常來講,它們包含有相關(guān)的函數(shù)集合來完成一項(xiàng)常用任務(wù)。典型的庫函數(shù)有屏幕處理函數(shù)(CURSES和NCURSES庫)和數(shù)據(jù)庫訪問函數(shù)(DBM庫)。標(biāo)準(zhǔn)系統(tǒng)函數(shù)通常存放在/LIB和/USR/LIB中。C編譯器需要被告知搜索哪個庫,否則缺省情況下只搜索標(biāo)準(zhǔn)庫。傳統(tǒng)靜態(tài)庫AEXAMPLESARE/USR/LIB/LIBCAAND/USR/X11/LIB/LIBX11AFORTHESTANDARDCLIBRARYANDTHEX11LIBRARY共享庫SOONATYPICALLINUXSYSTEM,THESHAREDVERSIONOFTHESTANDARDMATHLIBRARYIS/USR/LIB/LIBMSO,1GCC與GDB,15GDB調(diào)試和分析選項(xiàng)GDB基本命令FILE裝入想要調(diào)試的可執(zhí)行文件;KILL終止正在調(diào)試的程序;LIST列出產(chǎn)生執(zhí)行文件的源代碼的一部分;NEXT執(zhí)行一行源代碼但不進(jìn)入函數(shù)內(nèi)部;STEP執(zhí)行一行源代碼而且進(jìn)入函數(shù)內(nèi)部;RUN執(zhí)行當(dāng)前被調(diào)試的程序;QUIT終止GDB;WATCH使你能監(jiān)視一個變量的值而不管它何時被改變;BREAK在代碼里設(shè)置斷點(diǎn),這將使程序執(zhí)行到這里時被掛起;MAKE使你能不退出GDB就可以重新產(chǎn)生可執(zhí)行文件;SHELL使你能不離開GDB就執(zhí)行UNIXSHELL命令,21,1GCC與GDB,GDB調(diào)試舉例,/GDBTESTC/INCLUDEINTSUMINTMINTMAININTARGC,CHARARGV{INTI,N0SUM50FORI1I50I{NI}PRINTF“THESUMOF150ISD\N”,N},INTSUMINTM{INTI,N0FORI1IMI{NI}PRINTF“THESUMOF1DISD\N”,M,N},例GCCWALLGGDBTESTCOGDBTEST,22,1GCC與GDB,1啟動GDB開始調(diào)試,例1GDBGDBTEST,例2GDBGDBFILEGDBTEST,23,1GCC與GDB,2在GDB中查看源代碼,例GDBLIST,LIST也可以縮寫為L,24,1GCC與GDB,3在GDB中設(shè)置斷點(diǎn),例1GDBBREAK9,BREAK也可以縮寫為B,注意在GDB中利用行號設(shè)置斷點(diǎn),是指代碼運(yùn)行到對應(yīng)行號之前暫停;GDB中可以設(shè)置多個斷點(diǎn)。,25,1GCC與GDB,3在GDB中設(shè)置斷點(diǎn),例2GDBBREAKSUM,設(shè)置函數(shù)斷點(diǎn),在函數(shù)體開始處,例3GDBBREAK10IFI10,設(shè)置條件斷點(diǎn),26,1GCC與GDB,4開看斷點(diǎn)情況,例GDBINFOBREAK,27,1GCC與GDB,5運(yùn)行代碼,例GDBRUN,RUN也可以縮寫為R,28,1GCC與GDB,6查看變量,例GDBPRINTI,PRINT也可以縮寫為P;I為變量名,“N”是當(dāng)前變量值的引用標(biāo)記,29,1GCC與GDB,7單步運(yùn)行,單步運(yùn)行可以使用命令“STEP”和“NEXT”,它們之間的區(qū)別在于若有函數(shù)調(diào)用的時候“STEP”會進(jìn)入函數(shù)體,而“NEXT”不會進(jìn)入該函數(shù);,8恢復(fù)程序運(yùn)行,使用命令“CONTINUE”可以恢復(fù)程序正常運(yùn)行,直到遇到下一個斷點(diǎn)或者到程序結(jié)束;,GDB中程序有“運(yùn)行”、“暫?!焙汀巴V埂比N狀態(tài)?!皶和!睜顟B(tài)時,函數(shù)的地址、參數(shù)、局部變量都被壓入“棧”中,故可以查看函數(shù)的各種屬性;函數(shù)處于“停止”狀態(tài)時,“?!睍詣映蜂N,也就無法查看函數(shù)的信息了。,30,2MAKE工程管理器,21為什么要使用MAKE工作量問題對于擁有多個(上百個)源文件的軟件項(xiàng)目,只需編寫一次編譯過程,而不需要在每次源文件修改后重復(fù)輸入眾多的文件名和編譯命令進(jìn)行編譯;效率問題MAKE能夠根據(jù)文件的時間戳自動發(fā)現(xiàn)更新過的源文件,并通過讀入MAKEFILE文件來對更新的源文件進(jìn)行編譯而對其它文件只進(jìn)行鏈接操作。,31,2MAKE命令,22MAKEFILE的格式MAKEFILE是MAKE讀入的唯一配置文件,MAKEFILE文件通常包含如下內(nèi)容需要由MAKE創(chuàng)建的目標(biāo)體TARGET,通常是目標(biāo)文件或可執(zhí)行文件;要創(chuàng)建的目標(biāo)體所依賴的文件DEPENDENCY_FILE;創(chuàng)建每個目標(biāo)體時需要運(yùn)行的命令COMMMAND。,MAKEFILE格式TARGETDEPENDENCY_FILECOMMAND,COMMAND之前必須有個“TAB”,32,4鏈接特殊函數(shù)庫,/FILENAMEISTEMPC/INCLUDEINTMAININTARGC,CHARARGV{DOUBLEVALUEVALUELOGARGCPRINTF“VALUEF\N“,VALUE}用命令GCC–OTEMPTEMPC編譯時出錯。修改命令GCC–OTEMPTEMPC–LM這里指明編譯時與數(shù)學(xué)庫LIBMA相鏈接,則可正確編譯。,假設(shè)有程序TEMPC如下,
下載積分: 4 賞幣
上傳時間:2024-01-06
頁數(shù): 33
大?。?1.09(MB)
子文件數(shù):
簡介:C語言程序設(shè)計(jì),第8章面向?qū)ο蠹夹g(shù)與C,81C的起源和特點(diǎn)82簡單的C程序83C程序的上機(jī)實(shí)現(xiàn)84C的輸入和輸出85設(shè)置函數(shù)參數(shù)的默認(rèn)值86內(nèi)聯(lián)函數(shù)87重載函數(shù)88變量的引用89面向?qū)ο蟮母拍詈退枷?10類和對象811構(gòu)造函數(shù)812析構(gòu)函數(shù)813繼承與派生類,81C的起源和特點(diǎn),早期的程序是用機(jī)器語言或者匯編語言編寫最早的高級語言是20世紀(jì)50年代中期出現(xiàn)的FORTRAN50年代后期的ALGOL語言提出了塊結(jié)構(gòu)的思想60年代的SIMULA67語言首次提出了對象的概念70年代的ADA語言是一種基于對象的語言,支持?jǐn)?shù)據(jù)抽象類型,隨后面出現(xiàn)的SMALLTALK語言豐富了面向?qū)ο蟮母拍?,是最具有影響的面向?qū)ο蟮恼Z言之一1972年在DECPDP11計(jì)算機(jī)上實(shí)現(xiàn)了最初的C語言1980年AT表示鍵入兩個實(shí)數(shù),分別賦給變量X和Y,相當(dāng)于C語言中的輸入命令SCANF“DD”,,82簡單的C程序,例83上例82還可以用自定義函數(shù)的方法來實(shí)現(xiàn),82簡單的C程序,C程序的一些簡單特點(diǎn)完整的C源程序文件由一個或多個文件組成,每個文件可以包含若干個函數(shù)。在完整的C程序中,可能會出現(xiàn)許多函數(shù),但程序中有且僅有一個主函數(shù)MAIN,程序的執(zhí)行總是從主函數(shù)MAIN開始執(zhí)行的,至于其它函數(shù)則是通過函數(shù)的嵌套調(diào)用來進(jìn)行;2在C中實(shí)現(xiàn)注釋有兩種方法,一種方法是可以沿用C語言中的’/’和’/’進(jìn)行注釋,它一般適用于有多行注釋信息的情況;另一種是使用符號//進(jìn)行注釋,//之后本行的所有字符都是注釋內(nèi)容。如果注釋信息只有一行文字,通常使用//注釋;3輸入/輸出時C程序經(jīng)常使用的頭文件IOSTREAMH頭文件,因?yàn)樵谶@個頭文件中定義了標(biāo)準(zhǔn)輸入和標(biāo)準(zhǔn)輸出操作,而C中經(jīng)常用到STDIOH這個頭文件;4C中主函數(shù)MAIN函數(shù)體也是用一對花括號’{‘和’}’括起來,體內(nèi)每條語句仍然以分號結(jié)束。如果主函數(shù)MAIN沒有明確的返回值,在C中MAIN的返回值類型就應(yīng)該定義為VOID類型,而在C中MAIN的返回值類型可以是VOID型的,但更多情況下默認(rèn)不寫(其實(shí)是INT型的)。,83C程序的上機(jī)實(shí)現(xiàn),完整的C上機(jī)過程包括編輯、編譯和連接、運(yùn)行這三個環(huán)節(jié)若是在MSDOS方式下,可以使用TURBOC或者BORLANDC如果是在WINDOWS9X/2000/XP/2003平臺下,可以使用MICROSOFTVISUALC,84C的輸入和輸出,對于輸入/輸出,C除了保留C語言中的SCANF和PRINTF這兩個函數(shù)外,還增加了標(biāo)準(zhǔn)輸入流CIN和標(biāo)準(zhǔn)輸出流COUT,后者這兩個標(biāo)準(zhǔn)流在IOSTREAMH頭文件中有定義,841用COUT輸出842用CIN輸入,841用COUT輸出,在C中,用COUT和插入運(yùn)算符配合使用共同完成數(shù)據(jù)的鍵盤輸入,使用時可以不用指定數(shù)據(jù)類型。FLOATXINTNCINXN作用從鍵盤上分別輸入一個實(shí)數(shù)和一個整數(shù),然后把實(shí)數(shù)賦給變量X,把整數(shù)賦給變量N。鍵入時注意兩個數(shù)之間要用空格分隔,輸入格式如下325↙上述的輸入語句相當(dāng)于C中的SCANF“FD”,,842用CIN輸入,例84用CIN和COUT實(shí)現(xiàn)的輸入和輸出舉例,85設(shè)置函數(shù)參數(shù)的默認(rèn)值,在進(jìn)行函數(shù)定義(或函數(shù)說明)時,C允許給一個或多個形參指定默認(rèn)值(亦稱缺省值),使得函數(shù)調(diào)用更加方便,程序設(shè)計(jì)更加靈活。下面來看一個使用了參數(shù)默認(rèn)值的示例INTADD3INTINTA,INTB5,INTC8這是對用戶自定義函數(shù)ADD3INT進(jìn)行說明的語句,本例中使用了三個形參A、B和C。在函數(shù)說明時對后兩個參數(shù)B和C分別設(shè)置了默認(rèn)值,其中參數(shù)B的默認(rèn)值為5,參數(shù)C的默認(rèn)值為8。,85設(shè)置函數(shù)參數(shù)的默認(rèn)值,在設(shè)置函數(shù)默認(rèn)值時應(yīng)注意應(yīng)該從函數(shù)形參表中最右邊的那個參數(shù)開始設(shè)置默認(rèn)值,指定順序應(yīng)從右向左。在已指定了默認(rèn)值的參數(shù)的右邊不允許再出現(xiàn)尚未指定默認(rèn)值的參數(shù)。因此在設(shè)置函數(shù)默認(rèn)值時,既可以為形參表中的所有參數(shù)指定默認(rèn)值,也可以為形參表中最右邊的幾個連續(xù)參數(shù)指定默認(rèn)值當(dāng)函數(shù)被調(diào)用時,如果指定了具體的實(shí)參表,則調(diào)用時的實(shí)參值將取代原來參數(shù)的默認(rèn)值;如果沒有給定實(shí)參值,將沿用參數(shù)原來的默認(rèn)值,85設(shè)置函數(shù)參數(shù)的默認(rèn)值,在設(shè)置函數(shù)默認(rèn)值時應(yīng)注意指定函數(shù)參數(shù)默認(rèn)值的這種語法現(xiàn)象在程序設(shè)計(jì)時可有可無。當(dāng)需要對函數(shù)參數(shù)設(shè)置默認(rèn)值時,假如該函數(shù)還有函數(shù)聲明時,則默認(rèn)的參數(shù)值就應(yīng)該設(shè)置在函數(shù)聲明部分而不能設(shè)置在函數(shù)的定義部分;如果程序中沒有函數(shù)聲明,默認(rèn)的參數(shù)值將設(shè)置在函數(shù)定義部分在給函數(shù)參數(shù)設(shè)置默認(rèn)值時,被指定的默認(rèn)值不僅可以是常數(shù),也可以是表達(dá)式。全局變量可以被指定為參數(shù)的默認(rèn)值,但局部變量不行,因?yàn)槟J(rèn)參數(shù)的函數(shù)調(diào)用是在編譯時確定的,而局部變量在編譯時無法確定,85設(shè)置函數(shù)參數(shù)的默認(rèn)值,例85分析下面程序的輸出結(jié)果,要求熟悉默認(rèn)參數(shù)的用法,第一次調(diào)用由于沒有指定實(shí)參表,三個參數(shù)都采用原來的默認(rèn)值(1、2、3);第二次調(diào)用只有一個實(shí)參,指定了第一個參數(shù)的實(shí)參值,其余兩個參數(shù)沿用默認(rèn)值,此時的實(shí)參值為(4、2、3);第三次調(diào)用指定了兩個實(shí)參,指定了前兩個參數(shù)的實(shí)參值,第三個參數(shù)沿用默認(rèn)值,此時的實(shí)參值為(4、5、3);第四次調(diào)用指定了三個實(shí)參,表示三個參數(shù)全部都用新的實(shí)參值(4、5、6),原來設(shè)置的參數(shù)默認(rèn)值無效。,85設(shè)置函數(shù)參數(shù)的默認(rèn)值,例86分析程序的運(yùn)行結(jié)果,了解全局變量充當(dāng)參數(shù)的默認(rèn)值,86內(nèi)聯(lián)函數(shù),在設(shè)計(jì)程序時,合理地使用函數(shù),能做到“一次定義,多次使用”,實(shí)現(xiàn)了程序代碼和數(shù)據(jù)的共享,減少了程序的目標(biāo)代碼。但是,調(diào)用函數(shù)時卻要花費(fèi)一定的時間和內(nèi)存空間來保存調(diào)用的現(xiàn)場,程序效率有所降低,特別是對于那些需要頻繁調(diào)用、但本身代碼并不大的函數(shù),效率尤為不高。為了解決這個問題,C引入了內(nèi)聯(lián)函數(shù)。當(dāng)一個使用了內(nèi)聯(lián)函數(shù)的源程序被編譯時,編譯系統(tǒng)會把程序中出現(xiàn)的調(diào)用內(nèi)聯(lián)函數(shù)的語句,直接用內(nèi)聯(lián)函數(shù)的函數(shù)體來替換,這樣處理雖然增加了最終的目標(biāo)代碼,但卻節(jié)省了調(diào)用過程中的時間和空間的開銷,另外由于內(nèi)聯(lián)函數(shù)的代碼往往比較小,這樣做對程序執(zhí)行的影響也較小,效率較高。對于代碼小而且訪問頻繁的函數(shù),適宜使用內(nèi)聯(lián)函數(shù)。,86內(nèi)聯(lián)函數(shù),內(nèi)聯(lián)函數(shù)的定義方法在定義函數(shù)時,要求在函數(shù)首部的最左邊,也就是函數(shù)返回值的類型名前面,加上內(nèi)聯(lián)函數(shù)的關(guān)鍵字INLINE,其余部分與傳統(tǒng)的函數(shù)定義相同。例定義一個用于計(jì)算兩個數(shù)之和的內(nèi)聯(lián)函數(shù)INLINEINTSUM2INTINTM,INTN{RETURNMN},86內(nèi)聯(lián)函數(shù),例87計(jì)算自然數(shù)1到10中各個數(shù)的立方值,86內(nèi)聯(lián)函數(shù),使用內(nèi)聯(lián)函數(shù)的注意要點(diǎn)內(nèi)聯(lián)函數(shù)內(nèi)不允許出現(xiàn)循環(huán)語句和開關(guān)語句,如果一個內(nèi)聯(lián)函數(shù)包含了這些語句,則按普通函數(shù)處理內(nèi)聯(lián)函數(shù)的函數(shù)體一般不宜過大,以1至5行為宜在以后的講述中我們還會學(xué)到類,在類體內(nèi)定義的成員函數(shù)都是內(nèi)聯(lián)函數(shù),87重載函數(shù),重載函數(shù)的定義重載函數(shù)是指同一個函數(shù)名稱對應(yīng)著多個不同的函數(shù)實(shí)現(xiàn)例定義重載函數(shù)ABS,用來計(jì)算3個不同類型數(shù)據(jù)的絕對值INTABSINTLONGABSLONGDOUBLEABSDOUBLE重載函數(shù)在功能上比較接近,在定義時要有所區(qū)別。各重載函數(shù)之間的差別主要表現(xiàn)在函數(shù)返回值的類型、函數(shù)參數(shù)的類型、函數(shù)參數(shù)的個數(shù)、函數(shù)參數(shù)的順序等方面的不同,系統(tǒng)會根據(jù)這些不同來選擇相應(yīng)的函數(shù)。僅僅靠函數(shù)返回值類型的不同來定義重載函數(shù)是不行的,因此在使用重載函數(shù)時,在函數(shù)名字相同的前提下要將上述的那些區(qū)別明顯地表現(xiàn)出來。,87重載函數(shù),使用重載函數(shù)時編譯系統(tǒng)會根據(jù)如下原則進(jìn)行選擇重載函數(shù)至少要在參數(shù)類型、參數(shù)個數(shù)、參數(shù)順序上要有所不同,僅僅在函數(shù)返回值類型上的不同是不夠的例在下面的三個函數(shù)聲明中INTMYFUNINT,DOUBLE/第一個函數(shù)/INTMYFUNDOUBLE,INT/第二個函數(shù)/VOIDMYFUNINT,DOUBLE/第三個函數(shù)/第一個函數(shù)和第二個函數(shù)可以重載,因?yàn)槎咴趨?shù)順序上不同;第二個函數(shù)和第三個函數(shù)也可以重載,因?yàn)樗鼈兊膮?shù)順序和返回值類型都不同。但第一個函數(shù)和第三個函數(shù)的形參表相同,僅僅在返回值類型上不同,因此它們是不能重載的。,87重載函數(shù),使用重載函數(shù)時編譯系統(tǒng)會根據(jù)如下原則進(jìn)行選擇在使用重載函數(shù)時,需要逐一比較實(shí)參的類型與被調(diào)用的重載函數(shù)中的形參類型,從而決定調(diào)用哪個重載函數(shù)判斷過程如下查找是否存在一個嚴(yán)格匹配的重載函數(shù),如果找到了就調(diào)用那個函數(shù),否則將進(jìn)入第2步;通過內(nèi)部數(shù)據(jù)轉(zhuǎn)換查找一個匹配的,如果找到了就調(diào)用那個函數(shù),否則進(jìn)入第3步;通過用戶所定義的強(qiáng)制類型轉(zhuǎn)換來查找一個匹配的,如果找到了就調(diào)用那個函數(shù),否則提示函數(shù)調(diào)用時出錯。,87重載函數(shù),例假設(shè)重載函數(shù)FUN有如下兩種形式VOIDMYFUNINTVOIDMYFUNDOUBLE對于下列條件的函數(shù)調(diào)用,函數(shù)FUN的匹配情況如下MYFUN1//匹配VOIDMYFUNINT,為嚴(yán)格匹配MYFUN15//匹配VOIDMYFUNDOUBLE,為嚴(yán)格匹配MYFUN‘M’//匹配VOIDMYFUNINT,這是內(nèi)部數(shù)據(jù)轉(zhuǎn)換后的匹配MYFUNDOUBLE5//匹配VOIDMYFUNDOUBLE,這是強(qiáng)制類型的匹配使用重載函數(shù)時的注意事項(xiàng)不能用類型定義語句TYPEDEF定義的類型名來區(qū)分重載函數(shù)的參數(shù)類型在定義重載函數(shù)時,應(yīng)注意同名函數(shù)應(yīng)該具有相同的功能,如果讓重載函數(shù)去執(zhí)行不同的功能,這是不好的編程風(fēng)格,例88下列程序中定義了求幾個整數(shù)最大值的重載函數(shù),閱讀程序?qū)懗鲞\(yùn)行結(jié)果,88變量的引用,881引用的概念882引用作函數(shù)參數(shù),881引用的概念,引用(REFERENCE)的定義簡單地說,引用就是某個變量(或?qū)ο螅┑膭e名建立引用的格式類型名INT,在上面這個例子中,INTINTINT(注意這四種書寫格式中空格的位置),881引用的概念,例89閱讀程序?qū)懗鲞\(yùn)行結(jié)果,881引用的概念,引用是C中的概念,C中沒有這一概念,引用與指針不同,不能把二者混淆起來指針是變量,有獨(dú)立的內(nèi)存單元,而引用不是變量,引用和與它捆綁在一起的變量(或?qū)ο螅┱加猛粌?nèi)存單元;指針可以被引用,而引用不能再次被引用;指針可以作為數(shù)組元素,而引用不能作為數(shù)組元素。指針作為數(shù)組元素時該數(shù)組稱為指針數(shù)組;可以有空的指針,但不能有空引用,882引用作函數(shù)參數(shù),在定義函數(shù)時形參可以是引用引用充當(dāng)函數(shù)參數(shù)時傳遞的是地址,與指針變量作函數(shù)參數(shù)所起的作用相同一般地,引用作函數(shù)參數(shù)時程序的可讀性要好些,這是因?yàn)楫?dāng)引用作函數(shù)形參時,調(diào)用函數(shù)時的實(shí)參可以用變量名(或者表達(dá)式),這與傳統(tǒng)意義上的傳值調(diào)用相似。與之相反,如果是指針變量用作函數(shù)參數(shù),則函數(shù)調(diào)用時實(shí)參必須是地址,882引用作函數(shù)參數(shù),例810定義一個函數(shù)SWAP來交換兩個INT變量的值,要求用指針變量作函數(shù)參數(shù),882引用作函數(shù)參數(shù),例811定義一個函數(shù)SWAP來交換兩個INT變量的值,要求用引用作函數(shù)參數(shù),89面向?qū)ο蟮母拍詈退枷?891面向?qū)ο蟮母拍?92面向?qū)ο蠓椒ㄅc結(jié)構(gòu)化方法的比較893面向?qū)ο笙到y(tǒng)的特性,891面向?qū)ο蟮母拍?一、對象的概念對象有兩方面的含義,即在客觀世界中的含義和在程序世界中的含義客觀世界中的任何一個事物都可以看成對象在程序世界中,對象是問題空間中的個體或事物的抽象表示,是其屬性和相關(guān)操作的結(jié)合體。屬性表示了對象的性質(zhì),屬性值刻劃了對象的所有可能的狀態(tài);與屬性相關(guān)的操作表示了對象的行為,施加給對象的操作會引起對象狀態(tài)的變化對象是面向?qū)ο笙到y(tǒng)中最基本的概念,是問題空間中對客觀事物的一種抽象表示,也是應(yīng)用系統(tǒng)的基本組成單位,891面向?qū)ο蟮母拍?二、類的概念在面向?qū)ο笙到y(tǒng)中,類是一種抽象機(jī)制,它是對一組具有共同屬性和行為的對象的一般描述類與對象的關(guān)系是一個抽象與具體的關(guān)系。類是把從具體的對象中抽取出來的共同屬性所形成的一般化定義,是對象的抽象,而對象則是類的一個實(shí)例,891面向?qū)ο蟮母拍?三、繼承的概念繼承是一個對象可以獲取另一個對象特性的機(jī)制類和類之間的繼承關(guān)系,是客觀世界中遺傳關(guān)系的直接模擬,它表示了類與類之間的內(nèi)在聯(lián)系類有父類和子類之分,父類也叫基類,子類又叫派生類。子類除了可以沿用父類的某些特征外,它還具有本身獨(dú)特的屬性和操作正是因?yàn)橛辛死^承,低層的類只需定義特定于它的特征,就可以共享高層的類特征了,891面向?qū)ο蟮母拍?四、消息的概念消息是向?qū)ο蟀l(fā)出的服務(wù)請求。消息的發(fā)送方是一個要求提供服務(wù)的對象,而消息的接收方是一個能夠提供服務(wù)的對象在面向?qū)ο蟮南到y(tǒng)中,各對象之間是相互獨(dú)立的,對象之間通過消息進(jìn)行聯(lián)系,891面向?qū)ο蟮母拍?面向?qū)ο蟪绦蛟O(shè)計(jì)(OBJECTORIENTEDPROGRAMMING,簡稱OOP)從問題空間中客觀存在的事物出發(fā)構(gòu)造軟件系統(tǒng),用對象這個封裝的單元來表示問題空間中的客觀實(shí)體,用消息傳遞來建立對象之間的聯(lián)系,把相同屬性和相同行為的對象歸為一類,通過在不同層次上運(yùn)用抽象的原則,就可以得到較一般的類和較特殊的類,892面向?qū)ο蠓椒ㄅc結(jié)構(gòu)化方法的比較,在問題抽象階段。結(jié)構(gòu)化方法以算法為核心,按照數(shù)據(jù)變換的過程進(jìn)行分解,重點(diǎn)是描述數(shù)據(jù)變換的功能模塊。面向?qū)ο蠓椒ㄊ且詳?shù)據(jù)為核心,強(qiáng)調(diào)問題空間中的對象模型在設(shè)計(jì)階段。結(jié)構(gòu)化方法采用自頂向下、逐步求精的指導(dǎo)思想,采用模塊化編程,各個模塊有可能保持較強(qiáng)的獨(dú)立性,但往往獨(dú)立于數(shù)據(jù)結(jié)構(gòu)。面向?qū)ο蠓椒ㄊ菑膶ο蟪霭l(fā),將對象的數(shù)據(jù)結(jié)構(gòu)和相應(yīng)的操作代碼集中在一個封裝的實(shí)體內(nèi),對象和對象之間通過消息進(jìn)行聯(lián)系結(jié)構(gòu)化方法的程序模型算法數(shù)據(jù)結(jié)構(gòu)面向?qū)ο蠓椒ǖ某绦蚰P蛯ο笙?893面向?qū)ο笙到y(tǒng)的特性,面向?qū)ο笙到y(tǒng)的三個特征封裝性、繼承性和多態(tài)性封裝性(ENCAPSULATION)在程序設(shè)計(jì)中,封裝性指的是把數(shù)據(jù)以及對數(shù)據(jù)的操作集中在一起所構(gòu)成的一個實(shí)體。用戶不必知道對象行為的實(shí)現(xiàn)細(xì)節(jié),只需要根據(jù)對象提供的外部接口來訪問對象。因此從用戶的角度看,這些對象的行為就象包含在一個“黑匣子”里,是隱蔽的和不可見的。封裝性是一種信息隱藏技術(shù),系統(tǒng)設(shè)計(jì)員會清楚地標(biāo)明提供的服務(wù)接口,服務(wù)的具體實(shí)現(xiàn)卻被屏蔽封裝著,用戶和應(yīng)用程序員只能使用對象提供的操作功能而不清楚內(nèi)部數(shù)據(jù)或操作代碼的實(shí)現(xiàn)細(xì)節(jié)。采用對象封裝機(jī)制的目的在于將對象的使用者和設(shè)計(jì)者分開。,893面向?qū)ο笙到y(tǒng)的特性,繼承性(INHERITANCE)繼承所表達(dá)的是類與類之間的相互關(guān)系,使得某類對象可以繼承另一類對象的特征和功能,實(shí)現(xiàn)了信息共享和代碼重用,減少了冗余。在繼承層次結(jié)構(gòu)中,父類稱為基類,子類稱為派生類。具體地說,如果類B繼承了類A,則類B中的對象就具有了類A對象的一切特征(指數(shù)據(jù)屬性)和功能(指操作),我們就稱類A為基類(或父類),稱類B為類A的派生類(或子類)。繼承機(jī)制帶來的最大優(yōu)勢在于軟件系統(tǒng)易于擴(kuò)充,降低了軟件開發(fā)的費(fèi)用和復(fù)雜性,因此面向?qū)ο蠓椒ǚ浅_m合于開發(fā)大型軟件系統(tǒng)。,893面向?qū)ο笙到y(tǒng)的特性,多態(tài)性(POLYMORPHISM)多態(tài)性描述的是同一個消息可以根據(jù)發(fā)送消息對象的不同而采取不同的行為方式。C支持的多態(tài)性有兩種,即編譯時的多態(tài)和運(yùn)行時的多態(tài)。編譯時的多態(tài)是通過重載來實(shí)現(xiàn)的,到底執(zhí)行哪個重載版本在編譯時就可以知道,所以是相對靜態(tài)的多態(tài);運(yùn)行時的多態(tài)是通過虛函數(shù)來實(shí)現(xiàn)的,到底運(yùn)行哪個函數(shù)版本需要在運(yùn)行時找出發(fā)送消息的對象來確定,編譯器在編譯時采用動態(tài)聯(lián)編的手段。,810類和對象,8101類的定義8102對象的定義8103對象的成員表示,8101類的定義,類的定義格式分為兩大部分,即說明部分和實(shí)現(xiàn)部分。說明部分用來說明該類中的多個成員(包括被說明的數(shù)據(jù)成員和成員函數(shù)),而實(shí)現(xiàn)部分用來描述說明部分中成員函數(shù)的實(shí)現(xiàn)(或定義)。一般地,類的說明部分放在類體內(nèi),告訴使用者“做什么”,而類的實(shí)現(xiàn)部分放在類體外,告訴使用者“怎么做”。當(dāng)然也有些簡單的類將說明部分和實(shí)現(xiàn)部分合并在一起,都放在類體內(nèi)。,8101類的定義,類的一般定義格式CLASS類名//說明部分{PUBLIC公有的數(shù)據(jù)和成員函數(shù)PRIVATE私有的數(shù)據(jù)和成員函數(shù)}//實(shí)現(xiàn)部分各成員函數(shù)的實(shí)現(xiàn),8101類的定義,定義一個類時要注意以下幾點(diǎn)CLASS是定義類的關(guān)鍵字,習(xí)慣上用字母T開頭的標(biāo)識符表示類名,以區(qū)別對象名和函數(shù)名。類體中包含的數(shù)據(jù)成員和成員函數(shù)的說明或定義,用一對花括號{和}括起來從訪問權(quán)限上看,類的成員分為三大類公有的(PUBLIC)私有的(PRIVATE)受保護(hù)的(PROTECTED)成員函數(shù)必須在類體內(nèi)給出原型說明,位置在類體內(nèi)或者類體外。放在類體內(nèi)的函數(shù)被默認(rèn)為是內(nèi)聯(lián)函數(shù),而放在類體外定義的函數(shù)是一般函數(shù)。如果要定義內(nèi)聯(lián)函數(shù),只需在函數(shù)首部的最前面加上關(guān)鍵字INLINE,8101類的定義,在類體外定義成員函數(shù)時的格式{}其中作用域運(yùn)算符是用來標(biāo)識某個成員函數(shù)是屬于哪個類的。,8101類的定義,例812給出一個關(guān)于日期類的定義。類TDATE的體內(nèi)一共說明了6個成員,其中3個成員函數(shù)是公有的PUBLIC,3個數(shù)據(jù)成員是私有的PRIVATE。為了敘述方便,我們把類TDATE的定義內(nèi)容全部寫入一個名叫TDATEH的頭文件中,8101類的定義,例813定義類的時候,成員函數(shù)的定義部分除了可以寫類體外(如例812所示),也可以寫在類體內(nèi)。,8102對象的定義,對象的定義格式如下類名對象名表類名是待定義的對象所屬的類的名字,這個類要求事先已經(jīng)定義好了在定義對象時,直接用類名就可以了,無需在類名前再加上關(guān)鍵字CLASS對象名表中可以是一個或多個對象名,多個對象名之間用逗號分隔,可以是一般簡單的對象名、指向?qū)ο蟮闹羔樏蛞妹蛘呤菍ο髷?shù)組名例為前面已經(jīng)有所定義了的類TDATE定義了幾個對象TDATEDATE1,DATE2,PDATE,,8103對象的成員表示,一般對象的成員表示如下對象名數(shù)據(jù)成員名對象名成員函數(shù)名參數(shù)表指向?qū)ο蟮闹羔樀某蓡T表示如下對象指針名數(shù)據(jù)成員名對象指針名成員函數(shù)名參數(shù)表或者對象指針名數(shù)據(jù)成員名對象指針名成員函數(shù)名參數(shù)表,8103對象的成員表示,例814分析程序的運(yùn)行結(jié)果,類TDATE定義在頭文件TDATEH之中(見例812)。程序中定義了兩個對象D1和D2,通過成員函數(shù)SETDATE分別給兩個對象的各數(shù)據(jù)成員賦值,調(diào)用成員函數(shù)ISLEAPYEAR判斷D1和D2對應(yīng)的年是否為閏年,通過調(diào)用成員函數(shù)PRINT在屏幕顯示D1和D2的私有數(shù)據(jù)成員年、月、日的值。,811構(gòu)造函數(shù),構(gòu)造函數(shù)(CONSTRUCTOR)是一種特殊的成員函數(shù)與類中的其它成員函數(shù)不一樣,構(gòu)造函數(shù)不需要用戶調(diào)用,它是在建立一個對象時由系統(tǒng)自動執(zhí)行,于是完成了對新建對象的初始化構(gòu)造函數(shù)的名字與類名相同,它可以帶一個參數(shù)或者多個參數(shù),也可以沒有參數(shù)。在定義和說明構(gòu)造函數(shù)時,不必指明函數(shù)的類型,因?yàn)樗鼪]有返回值,更不需要加VOID類型說明構(gòu)造函數(shù)的說明部分一般放在類體中,至于函數(shù)定義部分,可以放在類體內(nèi),也可以放在類體外,例815利用構(gòu)造函數(shù)完成對新創(chuàng)建的對象的初始化,例816定義構(gòu)造函數(shù)給兩個不同的對象賦予不同的初值,例817定義一個重載的構(gòu)造函數(shù),811構(gòu)造函數(shù),默認(rèn)的構(gòu)造函數(shù)是無參數(shù)的空函數(shù),定義格式如下類名默認(rèn)構(gòu)造函數(shù)名{}默認(rèn)構(gòu)造函數(shù)名與類同名,由于無參數(shù),因此默認(rèn)構(gòu)造函數(shù)不能重載當(dāng)定義一個沒有給定初始值的對象時,系統(tǒng)會自動調(diào)用默認(rèn)構(gòu)造函數(shù),對新創(chuàng)建的對象進(jìn)行初始化。當(dāng)該對象的存儲屬性是外部的(EXTERN)或靜態(tài)的(STATIC),它的所有數(shù)據(jù)成員將被初始化為0(或空)。如果對象是自動的(AUTO或省略存儲屬性),則在使用前必須對該對象賦初值,假設(shè)在沒有為對象賦初值之前就已經(jīng)使用了數(shù)據(jù)成員,那將是無意義的,812析構(gòu)函數(shù),析構(gòu)函數(shù)(DESTRUCTOR)與構(gòu)造函數(shù)(CONSTRUCTOR)的作用相反。當(dāng)對象的生存期結(jié)束時,系統(tǒng)將自動調(diào)用析構(gòu)函數(shù)來釋放這個對象析構(gòu)函數(shù)也是一種特殊的成員函數(shù),其函數(shù)名也與類名相同,為了與構(gòu)造函數(shù)名區(qū)分開,特意在類名前加上符號,以示析構(gòu)析構(gòu)函數(shù)沒有參數(shù),也不能指定函數(shù)返回值類型(包括VOID類型),因此析構(gòu)函數(shù)不能重載,而且在一個類中只能定義一個析構(gòu)函數(shù)析構(gòu)函數(shù)的說明一般放在類體內(nèi),它的函數(shù)體可以寫在類體內(nèi),也可以寫在類體外,812析構(gòu)函數(shù),在以下兩種情況下,析構(gòu)函數(shù)將由系統(tǒng)自動執(zhí)行當(dāng)一個對象的生存期結(jié)束時,將自動調(diào)用析構(gòu)函數(shù)來釋放該對象使用NEW運(yùn)算符創(chuàng)建的對象,在使用DELETE運(yùn)算符釋放該對象時,系統(tǒng)將自動調(diào)用析構(gòu)函數(shù)如果類中沒有定義析構(gòu)函數(shù),系統(tǒng)將自動生成一個默認(rèn)的析構(gòu)函數(shù)。默認(rèn)析構(gòu)函數(shù)定義格式如下類名默認(rèn)析構(gòu)函數(shù)名{}其中,默認(rèn)析構(gòu)函數(shù)名與類名相同,該析構(gòu)函數(shù)不進(jìn)行任何操作。,例818分析下面程序的運(yùn)行結(jié)果,說明構(gòu)造函數(shù)和析構(gòu)函數(shù)是如何被調(diào)用的。,812析構(gòu)函數(shù),813繼承與派生類,8131繼承與派生類的概念8132派生類的定義格式8133公有派生類8134私有派生類8135保護(hù)成員,8131繼承與派生類的概念,繼承是C的一個重要機(jī)制,它能自動地為一個類提供來自另一個類的數(shù)據(jù)和操作,使得用戶可以在一個現(xiàn)有的類的基礎(chǔ)上,很快地建立起一個新的類,而不必從零開始重新設(shè)計(jì),實(shí)現(xiàn)了代碼的共享和重用。,在左邊這個樹型結(jié)構(gòu)圖中,最高層是抽象的,以下每一層都是上一層的具體化,從圖中可以看出低層具有高層的特征。例如一旦選擇了丹頂鶴,就不用再說丹頂鶴有羽毛長翅膀了,因?yàn)檫@些特征丹頂鶴已經(jīng)從鳥類中繼承了。,8131繼承與派生類的概念,在面向?qū)ο蟮姆椒ㄖ?,繼承是針對類而言的。通過繼承的機(jī)制,能夠通過已有的類型來定義新的類型。這樣,所定義的新類型在擁有原來類型屬性的同時,還擁有新的屬性,我們稱已存在的被用來生成新類型的類為基類,而從基類中派生出來的新類稱為派生類。在C中,派生類可以從一個基類(或多個基類)中派生得到。從一個基類中派生的繼承方式稱為單繼承,從多個基類中派生的繼承方式稱為多繼承。簡單地說,單繼承方式的派生類只有一個基類,而多繼承方式的派生類有多個基類。,8131繼承與派生類的概念,圖82所示的為單繼承,類B和類C是兩個不同的派生類,但它們都是從類A中派生出來的。圖83所示的是多繼承,類Z是由類X和類Y這兩個類派生出來的。,單繼承和多繼承舉例,8132派生類的定義格式,單繼承派生類的定義格式CLASS派生類名繼承方式基類名{派生類新增成員的定義};其中派生類是按指定的繼承方式從基類中派生出來的,具體的繼承方式有以下三種PUBLIC代表公有繼承方式PRIVATE代表私有繼承方式PROTECTED代表保護(hù)繼承方式默認(rèn)的繼承方式為PRIVATE,8132派生類的定義格式,多繼承派生類的定義格式CLASS派生類名繼承方式1基類名1,繼承方式2基類名2,{派生類新增成員的定義};與單繼承派生類的定義相比較,多繼承派生類在定義格式上的基類名較多,這些基類名彼此之間用逗號分隔,而且每個基類名前都有一個該基類的繼承方式說明默認(rèn)的繼承方式為私有繼承方式(PRIVATE),8132派生類的定義格式,例819定義一個學(xué)生類TSTUDENT,其數(shù)據(jù)成員包括學(xué)號、姓名和性別,對它進(jìn)行的操作是顯示每個學(xué)生的基本情況,若想在這個類的基礎(chǔ)上再添加年齡和年級信息。由于涉及到類中成員的修改,我們當(dāng)然可以拋開原來的類不管而重新定義一個新的類,但是利用類的繼承方法實(shí)現(xiàn)起來更方便。在原有類TSTUDENT的基礎(chǔ)上派生出一個新類TNEWSTUDENT。請看下面的例820,8132派生類的定義格式,例820定義一個派生類(在例819的基礎(chǔ)上),本例中TSTUDENT為基類(在例819中定義),TNEWSTUDENT是基類TSTUDENT的派生類,使用的繼承方式為PUBLIC派生類的成員函數(shù)NEWLIST調(diào)用了基類的公有成員函數(shù)LIST來顯示學(xué)生的學(xué)號、姓名和性別,8132派生類的定義格式,派生類中的成員包括原來基類中的成員和自己新增的成員對于派生類中新增的成員,如果在派生類定義中被定義為PRIVATE,它們只能通過同一類的成員函數(shù)進(jìn)行訪問;如果被定義為PUBLIC,則可以被外界所使用對于那些從基類中繼承過來的數(shù)據(jù)成員,并不是簡單地把基類中的PRIVATE和PUBLIC成員直接作為派生類的私有成員和公有成員,而要根據(jù)基類成員的訪問權(quán)限和派生類定義中的繼承方式共同決定(見表81),8133公有
下載積分: 4 賞幣
上傳時間:2024-01-06
頁數(shù): 80
大小: 0.94(MB)
子文件數(shù):
簡介:第3章簡單的C程序設(shè)計(jì),哈爾濱工業(yè)大學(xué)計(jì)算機(jī)學(xué)院蘇小紅SXHHITEDUCN,C語言大學(xué)實(shí)用教程,內(nèi)容提要,字符輸入輸出函數(shù)格式輸入輸出函數(shù),C語言中的語句,變量聲明語句INTX,Y表達(dá)式語句III1空語句復(fù)合語句{TXXYYT}控制語句,順序結(jié)構(gòu)程序的基本操作,如何在程序中給變量賦值賦值表達(dá)式語句賦值表達(dá)式;TOTALMPOW1R,N如何進(jìn)行數(shù)據(jù)的輸入輸出輸入從標(biāo)準(zhǔn)輸入設(shè)備上輸入數(shù)據(jù)到計(jì)算機(jī)內(nèi)存輸出將計(jì)算機(jī)內(nèi)存中的數(shù)據(jù)送到標(biāo)準(zhǔn)輸出設(shè)備C語言中輸入輸出操作通過調(diào)用標(biāo)準(zhǔn)庫函數(shù)來實(shí)現(xiàn)INCLUDE“STDIOH“在當(dāng)前目錄和TC指定的目錄中找該文件INCLUDE在由TC指定的文件目錄中找該文件,復(fù)合語句,在什么情況下使用復(fù)合語句條件語句和循環(huán)語句在語法上只允許帶一條語句當(dāng)分支和循環(huán)中需要進(jìn)行多項(xiàng)操作時,{TXXYYT},被當(dāng)作一條語句來處理,,例31,MAIN{INTA0{INTA1PRINTF“INAD\N“,A}PRINTF“OUTAD\N“,A},INA1OUTA0,空語句,空語句有什么作用什么也不做,只表示語句的存在自頂向下程序設(shè)計(jì)時用在那些未完成的模塊中延時用的空循環(huán),MAIN{DATAINITIALZEDATAPROCESSDATAOUTPUT},DATAINITIALZE{},字符輸入輸出函數(shù),字符輸出函數(shù)PUTCHARCH輸出一個字符CH字符輸入函數(shù)GETCHAR無參數(shù)函數(shù)值為從輸入設(shè)備接收的字符,INCLUDEMAIN{CHARCHPRINTF“PRESSAKEYANDTHENPRESSENTER“CHGETCHARPRINTF“YOUPRESSED“PUTCHARCHPUTCHAR\N},運(yùn)行程序,PRESSAKEYANDTHENPRESSENTER,311,,,,,,,,A↙,YOUPRESSED,A,例32,該語句的作用是什么,格式輸出函數(shù),格式輸出函數(shù)PRINTF格式控制字符串,輸出項(xiàng)表列輸出若干個任意類型的數(shù)據(jù)PRINTF“ADBF“,A,B,函數(shù)名,輸出表列,普通字符,,,,輸出常用輸出函數(shù)PRINTF將信息送到標(biāo)準(zhǔn)輸出(一般送到屏幕或特定窗口)PRINTF格式描述串,其他參數(shù)函數(shù)調(diào)用形式函數(shù)名,括號,函數(shù)參數(shù),多個參數(shù)用逗號分隔,語句程序基本單位,以分號為結(jié)束符PRINTF“GOODMORNING\N“一個完成輸出的語句,PRINTF的功能PRINTF格式描述串,其他參數(shù)第一個參數(shù)應(yīng)是字符串,可以有其他參數(shù)。如果“格式描述串”里沒有,也沒有其他參數(shù),PRINTF輸出格式描述串。,PRINTF“WELCOME\NTO\NBEIJING\N“輸出三行字符WELCOMETOBEIJING,轉(zhuǎn)換描述(描述數(shù)據(jù)的輸出轉(zhuǎn)換方式)格式串中開始的段意義特殊(“轉(zhuǎn)換描述”)每個轉(zhuǎn)換描述說明一參數(shù)的輸出形式(轉(zhuǎn)換方式)。特別注意()轉(zhuǎn)換描述和“其他參數(shù)”個數(shù)一致。轉(zhuǎn)換描述和對應(yīng)參數(shù)的類型必須一致。,輸出整數(shù)PRINTF”TESTDDD\N“,2,3,5,輸出長整數(shù)PRINTF”TESTLDD“,3L,5,D以帶符號十進(jìn)制整數(shù)輸出O以八進(jìn)制無符號整數(shù)輸出(無前導(dǎo)0)X以十六進(jìn)制無符號整數(shù)輸出(無前導(dǎo)0X)U以十進(jìn)制無符號整數(shù)輸出C以字符形式輸出單個字符S輸出一個字符串F以小數(shù)形式輸出浮點(diǎn)數(shù)(6位小數(shù))E以標(biāo)準(zhǔn)指數(shù)形式輸出(6位小數(shù))G選用F,E中輸出寬度較小的一種格式,PRINTF格式字符,L長整型整數(shù),加在D、O、X、U前LLONGDOUBLE型數(shù),加在F、E、G前M表示數(shù)據(jù)占用的最小寬度數(shù)據(jù)寬度大于M,按實(shí)際寬度輸出數(shù)據(jù)寬度小于M時,補(bǔ)空格N對實(shí)數(shù)表示輸出N位小數(shù)對字符串表示最多輸出的字符個數(shù)改變輸出內(nèi)容的對齊方式缺省為右對齊,PRINTF附加格式說明符,INCLUDEMAIN{FLOATF110015799,F21255,F317INTN1123,N245,N36PRINTF“PRINTFWITHOUTWIDTHORPRECISIONSPECIFICATIONS\N“PRINTF“F\NF\NF\N“,F1,F2,F3PRINTF“D\ND\ND\N“,N1,N2,N3PRINTF“PRINTFWITHWIDTHANDPRECISIONSPECIFICATIONS\N“PRINTF“52F\N61F\N30F\N“,F1,F2,F3PRINTF“\NM\N\N\N“,N1,N2,N3},例38,格式輸入函數(shù),格式輸入函數(shù)SCANF格式控制字符串,地址表列SCANF“D,F”,,格式輸入函數(shù),常見錯誤SCANF“D,F\N”,SCANF“D,F”,A,BSCANF“72F“,,D以帶符號十進(jìn)制形式輸入整型數(shù)據(jù)O以八進(jìn)制無符號形式輸入(無前導(dǎo)0)X以十六進(jìn)制無符號形式輸入(無前導(dǎo)0X)C以字符形式輸入單個字符S輸入字符串,以非空字符開始,遇第一個空白字符結(jié)束F以小數(shù)形式輸入浮點(diǎn)數(shù)E以標(biāo)準(zhǔn)指數(shù)形式輸入,SCANF格式字符,L加在D、O、X、U前輸入長整型加在F、E前輸入雙精度型L加在F、E前輸入LONGDOUBLE型H加在D、O、X前輸入短整型M表示數(shù)據(jù)占用的寬度本輸入項(xiàng)在讀入后不賦給相應(yīng)的變量,SCANF附加格式說明符,注調(diào)用函數(shù)PRINTF時,F(xiàn)LOAT類型的參數(shù)都是轉(zhuǎn)化為DOUBLE類型后再傳遞的,所以F可以輸出DOUBLE和FLOAT兩種類型的數(shù)據(jù),不必用LF輸出DOUBLE型數(shù)據(jù)。調(diào)用函數(shù)SCANF時,如果是FLOAT類型則對應(yīng)輸入轉(zhuǎn)換符為F,而DOUBLE類型的輸入轉(zhuǎn)換符為LF。例FLOATXDOUBLEYSCANF“FLF”,PRINTF“XF,YF”,X,Y,INCLUDEMAIN{INTA,BPRINTF“PLEASEINPUTAANDB“SCANF“DD“,PRINTF“AD,BD,ABD\N“,A,B,AB},PLEASEINPUTAANDB,A12,B34,AB46,1234↙,例,遇空格、TAB鍵時結(jié)束,INCLUDEMAIN{INTA,BPRINTF“PLEASEINPUTAANDB“SCANF“DD“,PRINTF“AD,BD,ABD\N“,A,B,AB},PLEASEINPUTAANDB,A12,B34,AB46,12↙,例,遇回車鍵時結(jié)束,34↙,INCLUDEMAIN{INTA,BPRINTF“PLEASEINPUTAANDB“SCANF““,PRINTF“AD,BD,ABD\N“,A,B,AB},PLEASEINPUTAANDB,A12,B34,AB46,1234↙,例,遇寬度時結(jié)束,INCLUDEMAIN{INTA,BPRINTF“PLEASEINPUTAANDB“SCANF““,PRINTF“AD,BD,ABD\N“,A,B,AB},PLEASEINPUTAANDB,A12,B3,AB15,123A↙,例,遇非法輸入時結(jié)束,INCLUDEMAIN{INTA,BPRINTF“PLEASEINPUTAANDB“SCANF“D,D“,PRINTF“AD,BD,ABD\N“,A,B,AB},PLEASEINPUTAANDB,A12,B34,AB46,12,34↙,例,這里逗號需要原樣輸入,INCLUDEMAIN{INTA,BPRINTF“PLEASEINPUTAANDB“SCANF“2D“,PRINTF“AD,BD,ABD\N“,A,B,AB},PLEASEINPUTAANDB,A12,B56,AB68,123456↙,例39,跳過一個輸入項(xiàng),INCLUDEMAIN{INTA,BSCANF“DD“,PRINTF“AD,BD\N“,A,B},問題1當(dāng)要求程序輸出結(jié)果為A12,B34時,用戶應(yīng)該如何輸入數(shù)據(jù),1234↙,輸入數(shù)據(jù)的格式控制例310,INCLUDEMAIN{INTA,BSCANF“DD“,PRINTF“AD,BD\N“,A,B},問題2當(dāng)限定用戶輸入數(shù)據(jù)以逗號為分隔符,即輸入數(shù)據(jù)格式為12,34↙時,應(yīng)修改程序中的哪條語句怎樣修改,SCANF“D,D“,,輸入數(shù)據(jù)的格式控制例310,INCLUDEMAIN{INTA,BSCANF“DD“,PRINTF“AD,BD\N“,A,B},問題3語句SCANF“DD“,修改為SCANF“AD,BD“,時,用戶應(yīng)該如何輸入數(shù)據(jù),A12,B34↙,輸入數(shù)據(jù)的格式控制例310,INCLUDEMAIN{INTA,BSCANF“DD“,PRINTF“AD,BD\N“,A,B},問題4限定用戶輸入數(shù)據(jù)為以下格式為1234↙同時要求程序輸出結(jié)果為A12,B34,SCANF““,,輸入數(shù)據(jù)的格式控制例310,INCLUDEMAIN{INTA,BSCANF“DD“,PRINTF“AD,BD\N“,A,B},問題5限定用戶輸入數(shù)據(jù)為以下格式為12↙34↙同時要求程序輸出結(jié)果為A“12“,B“34“,SCANF“DD“,PRINTF“A\“D\“,B\“D\“\N“,A,B,輸入數(shù)據(jù)的格式控制例310,INCLUDEMAIN{INTA,BSCANF“DD“,PRINTF“AD,BD\N“,A,B},問題6設(shè)計(jì)程序使得用戶可以以任意字符(回車、空格、制表符、逗號、其它)作為分隔符進(jìn)行數(shù)據(jù)的輸入,SCANF“DCD“,,輸入數(shù)據(jù)的格式控制例310,INCLUDEMAIN{INTDATA1,DATA2,SUMCHAROPPRINTF“PLEASEENTERTHEEXPRESSIONDATA1DATA2\N“SCANF“DCD“,PRINTF“DCDD\N“,DATA1,OP,DATA2,DATA1DATA2},PLEASEENTERTHEEXPRESSIONDATA1DATA2,第1次測試,123↙,1231293141,,,C格式符存在的問題及其解決例311,INCLUDEMAIN{INTDATA1,DATA2,SUMCHAROPPRINTF“PLEASEENTERTHEEXPRESSIONDATA1DATA2\N“SCANF“DCD“,PRINTF“DCDD\N“,DATA1,OP,DATA2,DATA1DATA2},PLEASEENTERTHEEXPRESSIONDATA1DATA2,第2次測試,123↙,12315,C格式符存在的問題及其解決例311,INCLUDEMAIN{INTDATA1,DATA2,SUMCHAROPPRINTF“PLEASEENTERTHEEXPRESSIONDATA1DATA2\N“SCANF“DCD“,PRINTF“DCDD\N“,DATA1,OP,DATA2,DATA1DATA2},PLEASEENTERTHEEXPRESSIONDATA1DATA2,第3次測試,123↙,12315,C格式符存在的問題及其解決例311,INCLUDEMAIN{INTACHARBFLOATCPRINTF“PLEASEINPUTANINTEGER“SCANF“D“,PRINTF“INTEGERD\N“,APRINTF“PLEASEINPUTACHARACTER“SCANF“C“,PRINTF“CHARACTERC\N“,BPRINTF“PLEASEINPUTAFLOATNUMBER“SCANF“F“,PRINTF“FLOATF\N“,C},PLEASEINPUTANINTEGER,希望得到的運(yùn)行結(jié)果,12↙,PLEASEINPUTANCHARACTER,A↙,PLEASEINPUTAFLOATNUMBER,35↙,INTEGER12,CHARACTERA,FLOATNUMBER3500000,C格式符存在的問題及其解決例312,INCLUDEMAIN{INTACHARBFLOATCPRINTF“PLEASEINPUTANINTEGER“SCANF“D“,PRINTF“INTEGERD\N“,APRINTF“PLEASEINPUTACHARACTER“SCANF“C“,PRINTF“CHARACTERC\N“,BPRINTF“PLEASEINPUTAFLOATNUMBER“SCANF“F“,PRINTF“FLOATF\N“,C},PLEASEINPUTANINTEGER,結(jié)果好像很奇怪嘛,12↙,PLEASEINPUTANCHARACTER,CHARACTER,PLEASEINPUTAFLOATNUMBER,35↙,INTEGER12,,FLOATNUMBER3500000,C格式符存在的問題及其解決例312,INCLUDEMAIN{INTACHARBFLOATCPRINTF“PLEASEINPUTANINTEGER“SCANF“D“,PRINTF“INTEGERD\N“,APRINTF“PLEASEINPUTACHARACTER“SCANF“C“,PRINTF“CHARACTERC\N“,BPRINTF“PLEASEINPUTAFLOATNUMBER“SCANF“F“,PRINTF“FLOATF\N“,C},C格式符存在的問題及其解決例312,輸入數(shù)據(jù)12后,按的回車鍵被當(dāng)作有效字符讀給字符型變量B了。,INCLUDEMAIN{INTACHARBFLOATCPRINTF“PLEASEINPUTANINTEGER“SCANF“D“,PRINTF“INTEGERD\N“,APRINTF“PLEASEINPUTACHARACTER“GETCHAR/吸收掉前面輸入整型數(shù)據(jù)后面鍵入的回車字符/SCANF“C“,PRINTF“CHARACTERC\N“,BPRINTF“PLEASEINPUTAFLOATNUMBER“SCANF“F“,PRINTF“FLOATF\N“,C},PLEASEINPUTANINTEGER,程序修改后得到的運(yùn)行結(jié)果,12↙,PLEASEINPUTANCHARACTER,A↙,PLEASEINPUTAFLOATNUMBER,35↙,INTEGER12,CHARACTERA,FLOATNUMBER3500000,C格式符存在的問題及其解決例312,INCLUDEMAIN{INTACHARBFLOATCPRINTF“PLEASEINPUTANINTEGER“SCANF“D“,PRINTF“INTEGERD\N“,APRINTF“PLEASEINPUTACHARACTER“SCANF“1S“,/第2種解決方案/PRINTF“CHARACTERC\N“,BPRINTF“PLEASEINPUTAFLOATNUMBER“SCANF“F“,PRINTF“FLOATF\N“,C},C格式符存在的問題及其解決例312,這里S前面的符號是數(shù)字1,不是字母L的小寫將程序的C改為1S用于讀入單個字符,由于1S完全忽略空格和回車符,可以避免回車符被作為單個字符讀入。,INCLUDEMAIN{INTDATA1,DATA2,SUMCHAROPPRINTF“PLEASEENTERTHEEXPRESSIONDATA1DATA2\N“SCANF“D1SD“,PRINTF“DCDD\N“,DATA1,OP,DATA2,DATA1DATA2},123↙,123↙,12↙↙3↙,再回頭來看例311,以任意分隔符輸入加法算式,可能嗎,這一章我們學(xué)習(xí)了,字符輸入函數(shù)GETCHAR字符輸出函數(shù)PUTCHAR格式輸入函數(shù)SCANF格式輸出函數(shù)PRINTF格式控制問題難點(diǎn),幾點(diǎn)忠告,不要拘泥于細(xì)節(jié)不要死記硬背在使用中慢慢掌握,作業(yè),作業(yè)P6467,35,36課堂練習(xí)32,33,3413,
下載積分: 4 賞幣
上傳時間:2024-01-06
頁數(shù): 45
大?。?1.02(MB)
子文件數(shù):