|
眾所周知,現(xiàn)代計(jì)算機(jī)產(chǎn)生的數(shù)學(xué)基礎(chǔ)是數(shù)理邏輯,物理基礎(chǔ)是開(kāi)關(guān)電路,計(jì)算機(jī)實(shí)際上是自動(dòng)執(zhí)行計(jì)算和邏輯操作的開(kāi)關(guān)電路系統(tǒng),且現(xiàn)在的絕大多數(shù)計(jì)算機(jī)都是馮·諾依曼存儲(chǔ)程序體系結(jié)構(gòu)的計(jì)算機(jī)。 1 存儲(chǔ)程序計(jì)算機(jī)傳奇1936年,阿蘭·麥席森·圖靈(Alan Mathison Turing, 1912~1954)為證明“不可計(jì)算數(shù)”的存在而提出圖靈機(jī)模型。這一“思想實(shí)驗(yàn)”抓住了數(shù)理邏輯和抽象符號(hào)處理的本質(zhì):一臺(tái)僅能處理0和1二元符號(hào)的機(jī)械設(shè)備,就能夠模擬任意計(jì)算過(guò)程——這就是現(xiàn)代計(jì)算機(jī)的概念模型。 1938年,克勞德·艾爾伍德·香農(nóng)(Claude Elwood Shannon, 1916~2001)開(kāi)創(chuàng)了開(kāi)關(guān)電路理論,在數(shù)理邏輯和物理實(shí)現(xiàn)之間架起了橋梁。 1940年,針對(duì)當(dāng)時(shí)紛紛出現(xiàn)的計(jì)算機(jī)特別是模擬計(jì)算機(jī),諾伯特·維納(Norbert Wiener, 1894~1964)提出計(jì)算機(jī)設(shè)計(jì)的五原則:(1)計(jì)算機(jī)負(fù)責(zé)運(yùn)算的中心部件不應(yīng)是模擬式,而應(yīng)是數(shù)字式;(2)開(kāi)關(guān)裝置應(yīng)該采用電子元件;(3)采用二進(jìn)制,而不是十進(jìn)制;(4)運(yùn)算和邏輯判斷都由機(jī)器完成,中間應(yīng)該沒(méi)有人的干預(yù);(5)內(nèi)部要有存貯數(shù)據(jù)的裝置,支持快速讀寫(xiě)。 1945年6月,約翰·馮·諾依曼(John von Neumann, 1903~1957)公開(kāi)了離散變量自動(dòng)電子計(jì)算機(jī)(Electronic Discrete Variable Automatic Computer, EDVAC)邏輯設(shè)計(jì)報(bào)告草案,提出了存儲(chǔ)和計(jì)算分離的存儲(chǔ)程序結(jié)構(gòu)(即馮·諾伊曼體系結(jié)構(gòu)),這實(shí)際是圖靈機(jī)的一種通用物理實(shí)現(xiàn)方案,同一套硬件(負(fù)責(zé)邏輯和計(jì)算的通用中央處理器)可以執(zhí)行多種功能(存放在存儲(chǔ)器中的程序)。 馮·諾伊曼體系結(jié)構(gòu)的核心概念是計(jì)算和存儲(chǔ)分離,數(shù)據(jù)和指令一起存儲(chǔ)(與通用圖靈機(jī)使用的“一條紙帶”是等價(jià)的)。
1946年,賓夕法尼亞大學(xué)研制成功第一臺(tái)電子數(shù)值積分計(jì)算機(jī)(Electronic Numerical Integrator And Computer, ENIAC)。
ENIAC實(shí)際上是用約1.8萬(wàn)個(gè)“電開(kāi)關(guān)”(電子管)搭建的大型開(kāi)關(guān)電路系統(tǒng),用電子管做為邏輯元件,尚未采用馮·諾伊曼體系結(jié)構(gòu),沒(méi)有存儲(chǔ)器,所以其程序并不是內(nèi)置的,而是通過(guò)開(kāi)關(guān)和重新調(diào)整電纜的連接方式來(lái)改變程序。ENIAC也并沒(méi)有采用二進(jìn)制而是十進(jìn)制,其輸入輸出設(shè)備采用IBM的穿孔卡片機(jī)。 打孔卡是早期計(jì)算機(jī)的信息輸入設(shè)備,通??梢?xún)?chǔ)存80列數(shù)據(jù)。打孔卡盛行于20世紀(jì)70年代中期。我們應(yīng)當(dāng)注意的是:打孔卡比計(jì)算機(jī)更在出現(xiàn)。其歷史可以追溯到1725年的紡織品行業(yè),用于機(jī)械化的織布機(jī)。和打孔卡一樣,也是紡織行業(yè)的機(jī)械化織布機(jī)率先使用打孔紙帶。在計(jì)算機(jī)上,打孔紙帶即可用于數(shù)據(jù)輸入,也可用于存儲(chǔ)輸出數(shù)據(jù)。紙帶帶上的每一行孔代表一個(gè)字符,穿孔紙帶上的當(dāng)前位置用5個(gè)孔位的編碼表示一個(gè)數(shù)字或字母。
EDSAC (Electronic Delay Storage Automatic Calculator,電子延遲存儲(chǔ)自動(dòng)計(jì)算機(jī))是世界上首次實(shí)現(xiàn)存儲(chǔ)程序計(jì)算機(jī)。EDSAC由英國(guó)劍橋大學(xué)威爾克斯 ( Maurice Vincent Wilkes )領(lǐng)導(dǎo)、設(shè)計(jì)和制造的,并于1949年投入運(yùn)行。它使用了水銀延遲線(xiàn)作存儲(chǔ)器,利用穿孔紙帶輸入和電傳打字機(jī)輸出。EDSAC 是第一臺(tái)采用馮·諾依曼體系結(jié)構(gòu)的計(jì)算機(jī)。威爾克斯后來(lái)摘取了1967年度計(jì)算機(jī)世界最高獎(jiǎng)——“圖靈獎(jiǎng) ”。 EDSAC的內(nèi)存槽5英尺長(zhǎng),內(nèi)含32個(gè)內(nèi)存位置。使用水銀延遲線(xiàn)作存儲(chǔ)器,分布在32個(gè)槽中,每個(gè)槽5英尺長(zhǎng),里面包含32個(gè)內(nèi)存位置,共1024個(gè)位置。建造時(shí)只實(shí)現(xiàn)了一半,512個(gè)字,第二組于1952年添加。1952年增加一個(gè)磁帶存儲(chǔ),但實(shí)際使用中不能良好工作。陰極射線(xiàn)管輸入采用5路的穿孔紙帶,使用電子紙帶讀入機(jī),速度為每秒個(gè)字符,1949年10月改進(jìn)為每秒16字符,1950年使用光電閱讀器,達(dá)到50字符每秒。輸出使用電傳打字機(jī),速度字符每秒,1951年添加一個(gè)16字符每秒的紙帶打孔機(jī)。另外,EDSAC可以外接陰極射線(xiàn)管(CRT),可以用來(lái)觀(guān)察寄存器的值。指令集由運(yùn)算器(ALU)、控制器來(lái)實(shí)現(xiàn)。 2 計(jì)算機(jī)指令集與機(jī)器語(yǔ)言在一臺(tái)馮諾依計(jì)算機(jī)中,最核心的就是CPU和內(nèi)存,指令和數(shù)據(jù)都存入在內(nèi)存當(dāng)中,CPU每次取出一條指令,譯碼、執(zhí)行,然后把結(jié)果寫(xiě)回內(nèi)存。 指令集是對(duì)CPU的抽象,文件是對(duì)輸入/輸出設(shè)備的抽象,虛擬存儲(chǔ)器是對(duì)程序存儲(chǔ)的抽象,進(jìn)程是對(duì)一個(gè)正在運(yùn)行的程序的抽象,而虛擬機(jī)是對(duì)整個(gè)計(jì)算機(jī)(包括操作系統(tǒng)、處理器和程序)的抽象。 計(jì)算機(jī)能夠執(zhí)行的指令是直接由硬件完成的,與硬件設(shè)計(jì)有關(guān)。不同的硬件設(shè)計(jì)產(chǎn)生不同的指令系統(tǒng)。因此,不同類(lèi)型的計(jì)算機(jī)所能執(zhí)行的指令是不同的。 程序是一個(gè)有序指令的集合,用來(lái)完成一定的功能,解決某一特定問(wèn)題。根據(jù)計(jì)算機(jī)的指令集就可以編寫(xiě)計(jì)算機(jī)能執(zhí)行的程序。 因?yàn)椴煌纳a(chǎn)廠(chǎng)商生產(chǎn)的計(jì)算機(jī)有不同的機(jī)器語(yǔ)言(二進(jìn)制指令集),所以,用機(jī)器語(yǔ)言編寫(xiě)的程序并不具有移植性。 3 由機(jī)器語(yǔ)言到匯編語(yǔ)言、高級(jí)語(yǔ)言二進(jìn)制代碼形式的語(yǔ)言稱(chēng)為機(jī)器語(yǔ)言。早在計(jì)算機(jī)誕生之初,人們就是直接用機(jī)器語(yǔ)言編程。但是,這種在計(jì)算機(jī)看來(lái)十分明了的機(jī)器語(yǔ)言程序,在人看來(lái)卻是一部“天書(shū)”。后來(lái),人們又將3個(gè)二進(jìn)制位合并在一起變成了八進(jìn)制。再后為,為了與字節(jié)對(duì)應(yīng),又將4個(gè)二進(jìn)制位合并在一起變成了十六進(jìn)制。將機(jī)器語(yǔ)言寫(xiě)成八進(jìn)制,或十六進(jìn)制形式,要比二進(jìn)制形式“好看”一些。 隨著計(jì)算機(jī)應(yīng)用不斷擴(kuò)大,程序需求量大增,編程工作量也越來(lái)越大,人們便產(chǎn)生了用符號(hào)代表機(jī)器指令的想法,設(shè)計(jì)出匯編語(yǔ)言(Assemble Language,又稱(chēng)符號(hào)語(yǔ)言)。比如,用ADD表示加法指令,用SUB表示減法指令,要比用二進(jìn)制0\1序列“00111011”表示某一條指令直觀(guān)得多。用匯編語(yǔ)言編寫(xiě)的程序稱(chēng)為匯編程序。將匯編程序送入計(jì)算機(jī),由計(jì)算機(jī)自動(dòng)地將匯編源程序翻譯成計(jì)算機(jī)能夠直接執(zhí)行的二進(jìn)制程序,而計(jì)算機(jī)的自動(dòng)翻譯功能是由專(zhuān)門(mén)的軟件--匯編程序(Assembler,又稱(chēng)匯編器)完成的,當(dāng)然,這個(gè)軟件也是人們事先編寫(xiě)的,并安裝在計(jì)算機(jī)系統(tǒng)中。一臺(tái)計(jì)算機(jī)配上匯編程序就相當(dāng)于人們“教會(huì)”計(jì)算機(jī)認(rèn)識(shí)匯編語(yǔ)言了。再后來(lái),人們又設(shè)計(jì)出反匯編程序,它能將機(jī)器語(yǔ)言程序反過(guò)來(lái)翻譯成匯編語(yǔ)言程序。通過(guò)反匯編,人們就可以讀懂安裝在計(jì)算機(jī)中的可執(zhí)行程序。
使用匯編語(yǔ)言減輕了不少人們的編程工作量,但是,匯編語(yǔ)言仍然十分原始,一條 匯編語(yǔ)句(也稱(chēng)為匯編指令)對(duì)應(yīng)一條機(jī)器指令,易讀性仍然很差。編制一個(gè)程序,哪怕只是用來(lái)完成簡(jiǎn)單計(jì)算任務(wù)的程序,通常需要成百上千條匯編指令。不僅編程效率低,程序不易調(diào)試,而且容易出錯(cuò)。更為麻煩的是,這種語(yǔ)言是完全按照計(jì)算機(jī)硬件設(shè)計(jì)的,不同各類(lèi)的計(jì)算機(jī)都有自己特有的機(jī)器語(yǔ)言和匯編語(yǔ)言,一種類(lèi)型的機(jī)器無(wú)法識(shí)別另一種類(lèi)型機(jī)器的機(jī)器語(yǔ)言,所以,匯編源程序缺乏可移植性。 人們都機(jī)器語(yǔ)言和匯編語(yǔ)言歸屬為低級(jí)語(yǔ)言。 匯編語(yǔ)言的出現(xiàn)具有劃時(shí)代的意義,它啟發(fā)人們,可以設(shè)計(jì)出更好用的語(yǔ)言,只需要通過(guò)翻譯器,將新語(yǔ)言的源程序翻譯成機(jī)器語(yǔ)言程序。于是,人們期待的脫離計(jì)算機(jī)機(jī)種的高級(jí)程序設(shè)計(jì)語(yǔ)言便陸續(xù)被設(shè)計(jì)出來(lái)。 高級(jí)語(yǔ)言引入變量、數(shù)組以及結(jié)構(gòu)化程序思想(分支、循環(huán)等控制結(jié)構(gòu))、函數(shù)(子程序)以及接近數(shù)學(xué)語(yǔ)言的表達(dá)式等語(yǔ)法成分,用接近英語(yǔ)口語(yǔ)的語(yǔ)句描述處理步驟(如if...then...else...),不僅容易理解和記憶,而且一條語(yǔ)句的處理能力相當(dāng)于幾條、幾十條、甚至幾百條 匯編指令,大大提高了編程效率。
指令與數(shù)據(jù)存儲(chǔ)的約定與機(jī)器語(yǔ)言、匯編語(yǔ)言、高級(jí)語(yǔ)言對(duì)比: 機(jī)器語(yǔ)言、匯編語(yǔ)言、高級(jí)語(yǔ)言完成一個(gè)簡(jiǎn)單程序的對(duì)比: 4 高級(jí)語(yǔ)言的結(jié)構(gòu)化程序思想20世紀(jì)60年代初,在提倡規(guī)則讓讀寫(xiě)程序更輕松的時(shí)代潮流中,結(jié)構(gòu)化程序設(shè)計(jì)應(yīng)運(yùn)而生。時(shí)至今日,大家對(duì)if、while這樣的語(yǔ)句早已習(xí)以為常。結(jié)構(gòu)化程序設(shè)計(jì)的初衷正是通過(guò)導(dǎo)入這些語(yǔ)句使代碼結(jié)構(gòu)理解變得簡(jiǎn)單。 結(jié)構(gòu)化程式設(shè)計(jì)(Structured programming),一種編程典范。它采用子程序、程式碼區(qū)塊(block structures)、for循環(huán)以及while循環(huán)等結(jié)構(gòu),來(lái)取代傳統(tǒng)的goto。希望借此來(lái)改善計(jì)算機(jī)程序的明晰性、品質(zhì)以及開(kāi)發(fā)時(shí)間,并且避免寫(xiě)出面條式代碼。
程序是命令的有序集合,命令執(zhí)行的順序即程序的結(jié)構(gòu)。一個(gè)程序的功能不僅取決于所選用的命令,還決定于命令執(zhí)行的順序。結(jié)構(gòu)化程序設(shè)計(jì)把程序的結(jié)構(gòu)限制為順序、分支和循環(huán)3種基本控制結(jié)構(gòu)。 5 高級(jí)語(yǔ)言的函數(shù)編程機(jī)制函數(shù)是編程語(yǔ)言的一種很重要的編程機(jī)制,用于將一段計(jì)算包裝起來(lái),然后可以多次調(diào)用。 函數(shù)把解決一個(gè)小問(wèn)題的代碼構(gòu)建成塊,可以反復(fù)調(diào)用,在邏輯上更易于閱讀和理解,也可以減少代碼的重復(fù)使用或冗余。另外,函數(shù)還可以組合成模塊,然后在其實(shí)模塊中可以引入包含有需要的函數(shù)的模塊,并通過(guò)模塊名和函數(shù)名來(lái)調(diào)用。 給函數(shù)添加參數(shù)的過(guò)程稱(chēng)為泛化(generalization)。因?yàn)樗鼤?huì)讓函數(shù)變得更通用。如你想計(jì)算一個(gè)正方形的面積,如果不提供參數(shù),只能是算某一個(gè)具體邊長(zhǎng)的正方形的面積,如果你將邊長(zhǎng)做為一個(gè)變量len,并提供給函數(shù)做為參數(shù),那在這個(gè)函數(shù)的新版本中,你就可以計(jì)算任意大小的正方形的面積。 函數(shù)為我們提供了在程序設(shè)計(jì)時(shí)的抽象機(jī)制,可以首先解決做什么的問(wèn)題,設(shè)計(jì)出程序的結(jié)構(gòu),通過(guò)函數(shù)機(jī)制做出接口,具體的實(shí)現(xiàn)可以逐步細(xì)化。 一個(gè)單元就是一個(gè)模塊。在任何一個(gè)單元中,分為接口和實(shí)現(xiàn)兩個(gè)部分。我們要用這個(gè)模塊,只需要理解接口中的調(diào)用函數(shù)用法即可。 函數(shù)就是一個(gè)功能部件,其頭部定義了它的接口,描述了函數(shù)的名字及其對(duì)參數(shù)的要求。使用者只需要考慮函數(shù)的功能是否滿(mǎn)足實(shí)際需要,還要保證調(diào)用式符合函數(shù)頭部的要求,并不需要知道函數(shù)實(shí)現(xiàn)的任何具體細(xì)節(jié)。 函數(shù)接口的作用。程序員各自開(kāi)發(fā)各自的模塊,只需要約定好互相調(diào)用的接口即可。 6 高級(jí)語(yǔ)言的抽象機(jī)制在程序開(kāi)發(fā)的實(shí)踐中人們逐漸認(rèn)識(shí)到,僅有計(jì)算層面的抽象機(jī)制和抽象定義還不夠,還需要考慮數(shù)據(jù)層面的抽象。能?chē)@一類(lèi)數(shù)據(jù)建立程序組件,將該類(lèi)數(shù)據(jù)的具體表示和相關(guān)操作的實(shí)現(xiàn)包裝成一個(gè)整體,也是組織復(fù)雜程序的一種有效技術(shù),可以用于開(kāi)發(fā)出各種有用的程序模塊。要把這種圍繞著一類(lèi)數(shù)據(jù)對(duì)象構(gòu)造的模塊做成數(shù)據(jù)抽象,同樣需要區(qū)分模塊的接口和實(shí)現(xiàn)。模塊接口提供使用它提供的功能所需的所有信息,但不涉及具體實(shí)現(xiàn)細(xì)節(jié)。另一方面,模塊實(shí)現(xiàn)者則要通過(guò)模塊內(nèi)部的一套數(shù)據(jù)定義和函數(shù)(過(guò)程)定義,實(shí)現(xiàn)模塊接口的所有功能,從形式上和實(shí)際效果上滿(mǎn)足模塊接口的要求。 C++包含一組內(nèi)置的數(shù)據(jù)類(lèi)型,例如字符型、整型和浮點(diǎn)型。每一種數(shù)據(jù)類(lèi)型都有一個(gè)唯一的允許聚會(huì)范圍及一組允許的操作和函數(shù)。例如,浮點(diǎn)型所允許的正負(fù)取值范圍與整型所允許的取值范圍就是不同的。平方根函數(shù)sqrt()既適用于整型數(shù)據(jù),也適用于浮點(diǎn)型數(shù)據(jù)。像length()這樣的字符串處理函數(shù)就不能應(yīng)用于整型或浮點(diǎn)型數(shù)據(jù)。 要使用一個(gè)整型或浮點(diǎn)型變量,不需要知道負(fù)數(shù)是怎樣存儲(chǔ)的或者用多少位去存儲(chǔ)一個(gè)數(shù)據(jù)值的這些細(xì)節(jié)。對(duì)于一個(gè)特定的數(shù)據(jù)類(lèi)型,只需要了解哪些函數(shù)和操作可以使用及這個(gè)數(shù)據(jù)類(lèi)型的合法取值范圍是什么。換句話(huà)說(shuō),數(shù)據(jù)類(lèi)型的實(shí)現(xiàn)細(xì)節(jié)對(duì)程序員是隱藏的,稱(chēng)為數(shù)據(jù)抽象。 在馮·諾依曼體系結(jié)構(gòu)中,程序代碼和數(shù)據(jù)都是以二進(jìn)制存儲(chǔ)的,因此,對(duì)計(jì)算機(jī)系統(tǒng)和硬件本身而言,數(shù)據(jù)類(lèi)型的概念其實(shí)是不存在的。機(jī)器指令和匯編語(yǔ)言中,數(shù)據(jù)對(duì)象是用二進(jìn)制數(shù)表示的,內(nèi)存里存的都是二進(jìn)制,對(duì)于內(nèi)存里存的內(nèi)容,可以說(shuō) “你認(rèn)為它是什么,它就是什么”。在高級(jí)語(yǔ)言中,為了有效地組織數(shù)據(jù),規(guī)范數(shù)據(jù)的使用,提高程序的可讀性,方便用戶(hù)使用,引入了整型,實(shí)型等基本數(shù)據(jù)類(lèi)型。不同的高級(jí)語(yǔ)言會(huì)定義不同的基本數(shù)據(jù)類(lèi)型。編程時(shí)只需知道如何使用這些類(lèi)型的變量(如何聲明,能執(zhí)行哪些運(yùn)算等),而不必了解變量的內(nèi)部數(shù)據(jù)表示形式和操作的具體實(shí)現(xiàn)。
盡管構(gòu)造數(shù)據(jù)類(lèi)型機(jī)制使得某些比較復(fù)雜的數(shù)據(jù)對(duì)象可以作為某種類(lèi)型的變量直接處理,但是這些類(lèi)型的表示細(xì)節(jié)對(duì)外是可見(jiàn)的,沒(méi)有相應(yīng)的保護(hù)機(jī)制,因而在使用中會(huì)帶來(lái)許多問(wèn)題。例如,用戶(hù)可在一個(gè)模塊中隨意修改該類(lèi)型變量的某個(gè)成分,而這種修改對(duì)處理該數(shù)據(jù)對(duì)象的其他模塊又會(huì)產(chǎn)生間接的影響,這對(duì)于一個(gè)由多人合作完成的大型軟件系統(tǒng)的開(kāi)發(fā)是很不利的。于是又出現(xiàn)了“信息隱藏”和抽象數(shù)據(jù)類(lèi)型的概念。 所謂抽象數(shù)據(jù)類(lèi)型(Abstract Data Type,ADT)是指這樣一種數(shù)據(jù)類(lèi)型,它不再單純是一組值的集合,還包括作用在值集上的操作的集合,即在構(gòu)造數(shù)據(jù)類(lèi)型的基礎(chǔ)上增加了對(duì)數(shù)據(jù)的操作,且類(lèi)型的表示細(xì)節(jié)及操作的實(shí)現(xiàn)細(xì)節(jié)對(duì)外是不可見(jiàn)得。之所以說(shuō)它是抽象的,是因?yàn)橥獠恐恢浪鍪裁?,而不知道它如何做,更不知道?shù)據(jù)的內(nèi)部表示細(xì)節(jié)。這樣,即使改變數(shù)據(jù)的表示和操作的實(shí)現(xiàn),也不會(huì)影響程序的其他部分。抽象數(shù)據(jù)類(lèi)型可達(dá)到更好的信息隱藏效果,因?yàn)樗钩绦虿灰蕾?lài)于數(shù)據(jù)結(jié)構(gòu)的具體實(shí)現(xiàn)方法,只要提供相同的操作,換用其他方法實(shí)現(xiàn)時(shí),程序無(wú)需修改,這個(gè)特征對(duì)于系統(tǒng)的維護(hù)很有利。 C++中的類(lèi)(Class)是抽象數(shù)據(jù)類(lèi)型的一種具體實(shí)現(xiàn),也是面向?qū)ο?Object-Oriented)程序設(shè)計(jì)語(yǔ)言中的一個(gè)重要概念。從結(jié)構(gòu)體過(guò)渡到類(lèi)是順其自然的事情,但是不能將C++看成是帶類(lèi)的C,因?yàn)樗鼛?lái)的是思考和解決問(wèn)題角度的轉(zhuǎn)變。不同于面向過(guò)程的程序設(shè)計(jì),在面向?qū)ο蟪绦蛟O(shè)計(jì)中,程序員面對(duì)的不再是一個(gè)個(gè)函數(shù)和變量,而是一個(gè)個(gè)對(duì)象。每個(gè)對(duì)象包含兩個(gè)部分:數(shù)據(jù)和方法,數(shù)據(jù)用來(lái)保存對(duì)象的屬性,而方法用來(lái)完成對(duì)數(shù)據(jù)的操作。對(duì)象與對(duì)象之間是通過(guò)消息進(jìn)行通信的。 7 面向過(guò)程和面向?qū)ο蟮木幊陶Z(yǔ)言典型的商用程序通常有幾百甚至上千行代碼。為了降低編寫(xiě)如此大規(guī)模代碼的復(fù)雜度,程序員必須將其分解為較小、較簡(jiǎn)單的模塊,例如函數(shù)和類(lèi)。函數(shù)和類(lèi)是構(gòu)造C++程序的基本模塊。 函數(shù)是用函數(shù)名來(lái)調(diào)用執(zhí)行的具有特定功能的語(yǔ)句塊。在C++的標(biāo)準(zhǔn)庫(kù)中有很多固有的、預(yù)先定義的庫(kù)函數(shù)。 在函數(shù)內(nèi)部定義的變量是auto(自動(dòng))存儲(chǔ)類(lèi)型。每次進(jìn)入函數(shù)(包括main())時(shí),都為每個(gè)auto存儲(chǔ)類(lèi)型的變量重新分配內(nèi)存空間;函數(shù)結(jié)束時(shí),將分配的內(nèi)存空間釋放,存儲(chǔ)在auto變量中的任何數(shù)值都將丟失。這樣的變量稱(chēng)為局部變量,只能在定義它的函數(shù)內(nèi)部訪(fǎng)問(wèn)。如果沒(méi)有指定變量的存儲(chǔ)類(lèi)型,那么變量的存儲(chǔ)類(lèi)型,那么變量的存儲(chǔ)類(lèi)型就默認(rèn)為auto。 和auto變量一樣,static變量對(duì)定義它們的函數(shù)而言,也是局部的。但不同于auto變量的是,static變量只分配一次存儲(chǔ)空間,因此即使函數(shù)結(jié)束后仍然保持其值不變。 變量的作用域指的是程序中可能訪(fǎng)問(wèn)到變量的部分,有兩種作用域類(lèi)型:塊作用域和全局作用域。 一個(gè)語(yǔ)句塊就是位于花括號(hào){和}之內(nèi)包含變量聲明的一條或多條語(yǔ)句。在一個(gè)語(yǔ)句塊內(nèi)聲明的變量只能在該語(yǔ)句塊中被訪(fǎng)問(wèn)。 由于全局變量可以在任何函數(shù)中被訪(fǎng)問(wèn),因此也可以被任何函數(shù)修改,這給程序的調(diào)試和維護(hù)帶來(lái)困難。全局變量不是函數(shù)實(shí)參的替代品。嚴(yán)格來(lái)講,除了局部變量之外,函數(shù)應(yīng)該只能訪(fǎng)問(wèn)函數(shù)形參列表中指定的數(shù)據(jù)。 對(duì)象是程序一個(gè)組成部分,它知道如何執(zhí)行特定的操作,知道如何去和程序的其它部分進(jìn)行交互。一個(gè)對(duì)象包含一個(gè)或多個(gè)數(shù)據(jù)值及應(yīng)用于這個(gè)對(duì)象的一些函數(shù),其中這些數(shù)據(jù)值定義了這個(gè)對(duì)象的狀態(tài)或者屬性,和對(duì)象關(guān)聯(lián)的函數(shù)表示可以對(duì)該對(duì)象做些什么及該對(duì)象是如何運(yùn)作的。對(duì)象可以是任何事物,例如人、計(jì)算機(jī),甚至是像銀行帳戶(hù)這樣的無(wú)形的東西。 類(lèi)同時(shí)定義了數(shù)據(jù)的類(lèi)型和可作用于這些數(shù)據(jù)之上的操作。類(lèi)把數(shù)據(jù)和函數(shù)包含在一起,成為一個(gè)整體。這個(gè)過(guò)程稱(chēng)為封裝。 類(lèi)的成員有私有成員和公有成員兩種。用關(guān)鍵字private和public指定類(lèi)的數(shù)據(jù)成員和成員函數(shù)的訪(fǎng)問(wèn)控制權(quán)限。被聲明為private的數(shù)據(jù)成員只能被這個(gè)類(lèi)的成員函數(shù)訪(fǎng)問(wèn),其他的非成員函數(shù)無(wú)權(quán)訪(fǎng)問(wèn),稱(chēng)為信息的隱藏。其目的是防止數(shù)據(jù)在這個(gè)類(lèi)外被修改。 聲明為public的數(shù)據(jù)成員可以在程序的任何部分被訪(fǎng)問(wèn)。公有成員函數(shù)稱(chēng)為類(lèi)的公共接口。 以上分析解決問(wèn)題所需步驟,用函數(shù)把這些步驟依次實(shí)現(xiàn),屬于面向過(guò)程的程序設(shè)計(jì)思路。 以上把構(gòu)成問(wèn)題的事務(wù)分解為各個(gè)對(duì)象,將數(shù)據(jù)(數(shù)據(jù)結(jié)構(gòu))和對(duì)數(shù)據(jù)的操作(方法或函數(shù))抽象、封裝到類(lèi)和對(duì)象,屬于面向?qū)ο蟮某绦蛟O(shè)計(jì)思路。建立對(duì)象目的,不是完成一個(gè)步驟,而是描述某個(gè)事務(wù)在解決整個(gè)問(wèn)題步驟中的行為。面向?qū)ο蠹夹g(shù)是一種以對(duì)象為基礎(chǔ),以事件或消息來(lái)驅(qū)動(dòng)對(duì)象執(zhí)行處理的程序設(shè)計(jì)技術(shù)。它具有抽象性、封裝性、繼承性及多態(tài)性等。 C語(yǔ)言是面向過(guò)程的編程,它最重要的特點(diǎn)是函數(shù),通過(guò)主main函數(shù)來(lái)調(diào)用各個(gè)子函數(shù)。程序運(yùn)動(dòng)的順序都是程序員事先決定好的。 C++兼有面向過(guò)程與面向?qū)ο蟮木幊?,?lèi)是它的主要特點(diǎn),在程序執(zhí)行過(guò)程中,先由主main函數(shù)進(jìn)入,定義一些類(lèi),根據(jù)需要執(zhí)行類(lèi)的成員函數(shù),過(guò)程的概念被淡化了(實(shí)際上過(guò)程還是有的,就是主函數(shù)的那些語(yǔ)句),以類(lèi)驅(qū)動(dòng)程序運(yùn)行,類(lèi)就是對(duì)象,所以我們稱(chēng)之為面向?qū)ο蟪绦蛟O(shè)計(jì)。 形象地理解,面向過(guò)程就是把所有的功能全部在一個(gè)大的類(lèi)里定義出來(lái),當(dāng)系統(tǒng)龐大時(shí),功能多了,各種操作之間的調(diào)用關(guān)系也很復(fù)雜,當(dāng)需要修改一個(gè)功能時(shí)就可能引發(fā)一連串的改動(dòng),使修改和維護(hù)成本很昂貴。面向?qū)ο笫前压δ芤詫?duì)象為基本單位進(jìn)行分類(lèi),這就是面向?qū)ο蟪绦蛟O(shè)計(jì)所常說(shuō)的類(lèi)。當(dāng)需要添加功能時(shí),只需修改相應(yīng)的類(lèi)和極小的其他部分,即可達(dá)到目的。 面向?qū)ο笤诜治龊徒鉀Q問(wèn)題的時(shí)候,將涉及的數(shù)據(jù)和數(shù)據(jù)的操作封裝在類(lèi)中,通過(guò)類(lèi)可以創(chuàng)建對(duì)象。例如,可以構(gòu)建一個(gè)Circle類(lèi)(表示圓的類(lèi)),它是半徑不同的所有圓的一個(gè)抽象描述。通過(guò)類(lèi)可以創(chuàng)建任意多個(gè)對(duì)象,這些對(duì)象之間是相互獨(dú)立的??梢杂蒀ircle創(chuàng)建圓c1和圓c2,而c1和c2是彼此獨(dú)立的對(duì)象。這樣,對(duì)于事務(wù)的管控力度,就由某個(gè)具體的對(duì)象擴(kuò)大到一個(gè)類(lèi),符合人們認(rèn)識(shí)事務(wù)的習(xí)慣。 class Circle{private: double m_dRadius;public: void SetR(double r) { m_dRadius = r; } double GetArea() { return(3.14*m_Radius * m_dRadius); }};面向過(guò)程與面向?qū)ο蟾饔袃?yōu)勢(shì): 8 相關(guān)問(wèn)題8.1 機(jī)器語(yǔ)言為什么要用難以理解、難以記憶的二進(jìn)制比特串來(lái)表示指令,而不用人們?nèi)菀桌斫獾姆?hào)來(lái)表示? 因?yàn)橛?jì)算機(jī)是由邏輯電路組成的,而0、1正好對(duì)應(yīng)于邏輯電路中的兩種電平信號(hào),可以直接翻譯成控制信號(hào),使計(jì)算機(jī)硬件實(shí)現(xiàn)比較容易。如果采用人比較容易理解的符號(hào),如英文、中文或者數(shù)學(xué)符號(hào),則計(jì)算機(jī)需要用硬件將這些符號(hào)翻譯成控制信號(hào),使硬件設(shè)計(jì)非常復(fù)雜,甚至無(wú)法實(shí)現(xiàn)。 8.2 為什么不直接用自然語(yǔ)言和計(jì)算機(jī)進(jìn)行交互,而要設(shè)計(jì)專(zhuān)門(mén)的程序設(shè)計(jì)語(yǔ)言? 自然語(yǔ)言太復(fù)雜,而計(jì)算機(jī)本身(機(jī)器語(yǔ)言)的功能又非常簡(jiǎn)單,如果要將自然語(yǔ)言作為人機(jī)交互的工具,編譯器的設(shè)計(jì)與實(shí)現(xiàn)必將非常的復(fù)雜。另外,自然語(yǔ)言太靈活,理解自然語(yǔ)言需要一些背景知識(shí),否則會(huì)產(chǎn)生二義性,這也給計(jì)算機(jī)實(shí)現(xiàn)帶來(lái)了很大的麻煩。 8.3 為什么不同類(lèi)型的計(jì)算機(jī)可以運(yùn)行同一個(gè)C++程序,而不同類(lèi)型的計(jì)算機(jī)不能運(yùn)行同一個(gè)匯編程序? 因?yàn)椴煌?lèi)型的計(jì)算機(jī)上有不同的C++編譯器,可以將同一個(gè)C++程序編譯成不同機(jī)器上的機(jī)器語(yǔ)言表示的目標(biāo)程序。而匯編程序僅是機(jī)器語(yǔ)言的另一種表現(xiàn)形式。不同類(lèi)型的計(jì)算機(jī)有不同的機(jī)器語(yǔ)言,也就有不同的匯編語(yǔ)言。 8.4 為什么在不同生產(chǎn)廠(chǎng)商生產(chǎn)的計(jì)算機(jī)上運(yùn)行C++程序需要使用不同的編譯器。 因?yàn)椴煌纳a(chǎn)廠(chǎng)商生產(chǎn)的計(jì)算機(jī)有不同的機(jī)器語(yǔ)言,所以需要不同的編譯器將同樣的C++程序翻譯成不同的機(jī)器語(yǔ)言。 8.5 什么是源程序?什么是目標(biāo)程序?為什么目標(biāo)程序不能直接運(yùn)行? 用某種程序設(shè)計(jì)語(yǔ)言寫(xiě)的程序稱(chēng)為源程序,源程序經(jīng)過(guò)編譯產(chǎn)生的機(jī)器語(yǔ)言的程序稱(chēng)為目標(biāo)程序。因?yàn)槌绦蚩赡苡玫搅艘恍┢渌绦騿T寫(xiě)好的程序,沒(méi)有這些工具程序的代碼整個(gè)程序就無(wú)法運(yùn)行,因此需要將目標(biāo)程序和這些工具的目標(biāo)程序鏈接在一起后才能運(yùn)行。 8.6 試列舉出高級(jí)語(yǔ)言的若干優(yōu)點(diǎn)(相比與機(jī)器語(yǔ)言)。 首先高級(jí)語(yǔ)言更接近于自然語(yǔ)言和人們熟悉的數(shù)學(xué)表示,學(xué)起來(lái)比較方便。 其次高級(jí)語(yǔ)言功能比機(jī)器語(yǔ)言強(qiáng)。一般的機(jī)器語(yǔ)言只能支持整數(shù)加法、移位、比較等操作,而高級(jí)語(yǔ)言能執(zhí)行復(fù)雜的算術(shù)表達(dá)式、關(guān)系表達(dá)式和邏輯表達(dá)式。高級(jí)語(yǔ)言可以使程序員在較高的抽象層次上考慮問(wèn)題,編程序比較容易。 第三,高級(jí)語(yǔ)言具有相對(duì)的機(jī)器獨(dú)立性,在一臺(tái)機(jī)器上用高級(jí)語(yǔ)言編寫(xiě)的程序可以在另外一臺(tái)不同廠(chǎng)商生產(chǎn)的計(jì)算機(jī)上運(yùn)行,這使得程序有較好的可移植性,有利于代碼重用。 -End- |
|
|