版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
第11章編碼設計與規(guī)范11.1程序設計語言11.2編碼規(guī)范11.3編碼風格11.4程序效率11.5編程安全11.6小結 11.1程序設計語言
11.1.1程序設計語言的基本概念
1.低級語言和高級語言
計算機剛問世的時候,它的硬件只能識別由字符0和1組成的二進制機器指令序列,也就是最初的機器指令程序。機器指令程序是最基本的計算機語言。機器語言與特定的計算機硬件相關,要求程序設計人員對計算機的內部硬件結構要有比較多的了解。由于機器指令程序是二進制的機器指令序列,所以,它的可讀性相當差,所編制出來的程序難以理解、修改和維護。為了提高程序設計的效率,人們用容易記憶的符號來代替機器指令,這些符號就是匯編指令。匯編語言是匯編指令的集合,它的使用提高了編程的效率,同時,使用匯編語言編寫的程序可讀性也有一定的提高。比如,匯編語言的加法用ADD表示,減法用SUB表示,乘法用MUL表示等。但匯編語言只是機器語言的簡單對應,匯編語言程序設計仍然與特定的計算機硬件緊密關聯(lián),效率不高。而且,采用匯編語言編寫的程序,要經匯編程序翻譯成機器語言程序,才能在計算機上運行。機器語言和匯編語言都是面向機器的,通常稱為低級語言。低級語言的共同點是面向機器,與機器的內部體系結構有著密切關系。不同的計算機通常有著不同的低級語言。用低級語言編碼難以掌握,編程過程中容易出錯,并且非專業(yè)人員難以弄懂。
與低級語言不同,高級語言是面向用戶和各種實際應用的,它的抽象程度更高,功能更強大。它不依賴于某種計算機硬件,通用性強,移植性好,而且在形式上與人們使用的自然語言比較接近,易學易懂,適合于推廣使用。高級語言對計算機的各種操作進行高度抽象,從而使得一個對底層硬件知之甚少的人也能用它來編寫程序。但用高級語言編寫的程序在執(zhí)行過程中需要解釋和編譯程序,所以程序的運行速度較低級語言程序慢。
2.匯編程序、編譯程序和解釋程序
程序設計語言是一套表達計算過程的符號系統(tǒng),其表達形式應該能夠同時被計算機和人所理解。高級語言接近于自然語言,使得程序設計語言易于掌握和運用。特別是面向對象程序設計語言,它從客觀世界所存在的對象實體出發(fā),力求貼近人們考慮問題的實際思維模式和習慣,使得運用程序設計語言對問題空間進行描述變得更加容易。
人們可以借用各種高級語言與計算機進行交互,但對于計算機來說,它能夠直接理解和執(zhí)行的,仍然只能是由二進制機器指令組成的機器指令程序。因此,使用其他程序設計語言編寫出來的程序代碼,需要最終翻譯為機器指令程序才能執(zhí)行。實現(xiàn)這些翻譯功能的程序稱為語言處理程序。翻譯程序就是指這樣一種程序,通過它能夠將使用高級語言編寫的源程序轉換成與之在邏輯上等價的低級語言形式的目標程序。常見的翻譯程序大致可以分為匯編程序、編譯程序和解釋程序。
通常所說的源程序,是指程序員使用某種高級語言或匯編語言編寫出來的程序代碼,這些程序代碼需要經過翻譯才能執(zhí)行。匯編程序對使用匯編語言編寫出來的源程序進行翻譯,得到可執(zhí)行的目標程序,然后在計算機上運行。如果要運行使用高級語言編寫出來的源程序,則需要相應的編譯程序或解釋程序,對源程序進行翻譯,從而使其可以在計算機上執(zhí)行。編譯程序首先將源程序翻譯成目標程序,然后再執(zhí)行該目標程序。如果編譯生成的目標程序是匯編語言形式,在編譯和運行階段之間就要添加一個匯編階段,把經過編譯生成的匯編語言目標程序匯編成機器語言目標程序。在編譯方式下,機器上運行的是與源程序等價的目標程序,源程序和編譯程序都不再參與目標程序的執(zhí)行過程。
解釋程序則是逐條讀出源程序中的語句并解釋執(zhí)行,即在解釋程序的執(zhí)行過程中并不產生目標程序,解釋一條語句就執(zhí)行一條語句。在解釋方式下,解釋程序和源程序(或其某種等價表示)要參與到程序的運行過程中,運行程序的控制權在解釋程序。典型的解釋型高級語言是BASIC語言。編譯程序和解釋程序也可以組合起來工作。比如,首先由編譯程序將源程序編譯成中間代碼,然后由解釋程序對這些中間代碼解釋執(zhí)行,這樣就既包含了編譯的過程,又包含了解釋的過程。
3.程序設計語言的定義
程序設計語言需要完整、精確的定義。如果沒有一種清楚的符號來表示語言結構的種種效果,那么我們將無法清楚地知道語言所描述的到底是什么,更無法從數(shù)學的角度系統(tǒng)地對程序的效果進行推理。另外,要實現(xiàn)高級語言與計算機內部體系結構無關,應該使用一種標準的方式來定義語言,使定義能夠被全世界所接受。比如標準化組織ANSI和ISO就已經對很多程序設計語言進行了嚴格的定義,這些語言包括Pascal、FORTRAN、C、C++、Ada、Prolog等。程序設計語言的定義一般包括3個方面:語法、語義和語用。
程序設計語言的語法和我們通常所使用的自然語言語法有很多相通之處,它決定了一些語言要素如何組合在一起構成其他語言要素的規(guī)則,即由程序語言的基本符號組成程序中的各個語法成分的一組規(guī)則。這些規(guī)則包括詞法規(guī)則和語法規(guī)則。其中,詞法規(guī)則是指由基本符號構成的符號(單詞)書寫規(guī)則,類似于自然語言中的單詞拼寫法。語法規(guī)則是指由符號(單詞)構成語法成分的規(guī)則,類似于自然語言中的遣詞造句,甚至組段謀篇。程序設計語言的定義是嚴格的,其語法可通過形式語言進行描述。幾乎所有的程序設計語言都使用上下文無關文法進行語法定義。
程序設計語言的語法是程序設計語言的有機組成部分,規(guī)定了程序的外觀結構。與語法相比,程序設計語言的語義更加復雜,難以用精確的方法進行描述。首先,人類語言本身的豐富性就已經使得“語義”可以從不同的角度去理解,從而得到不同的結果。另外,許多語句的含義是與上下文環(huán)境有關的,在不同語境中的含義并不完全相同。程序設計語言的語義是程序設計語言中按語法規(guī)則構成的各個語法成分的含義。其中,編譯時就可以確定的語法成分的含義稱為靜態(tài)語義,運行時刻才能確定的含義稱為動態(tài)語義。一個程序的語義決定了該程序執(zhí)行的效果,它本身取決于構成該程序的各個組成部分的語義。
語義主要是表明構成語言的各個符號和使用者的關系,與符號的來源、使用和影響有關。語言實現(xiàn)的語境則是指理解和實現(xiàn)程序設計語言的環(huán)境,這種環(huán)境主要包括程序的編譯環(huán)境和運行環(huán)境。11.1.2程序設計語言的發(fā)展及種類
1.程序設計語言的發(fā)展
從計算機開始得到廣泛應用至今,程序設計語言也經歷了很大的變化,種類已達上百種。今后程序設計語言將會繼續(xù)發(fā)展完善,從一開始的機器語言,到后來的匯編語言,再到現(xiàn)在的高級語言,并向更高級語言過渡。
程序設計語言有交流算法和計算機實現(xiàn)的雙重目的,它用于描述計算機上的運算,其歷史系于20世紀40年代起步的電子計算機的發(fā)展史。另外,程序設計語言還有一個相對獨立于機器的發(fā)展史,該歷史系于數(shù)學及數(shù)學概念的發(fā)展,主要焦點集中在程序設計語言的第二種重要功能:計算和算法的描述。
1)第一位程序員
完全用于計算的第一臺計算機是巴貝奇(Babbage)于1830~1840年發(fā)明的,通常稱為巴貝奇分析機。雖然該機器沒有完全建成,但它卻能執(zhí)行若干計算實例。這些實例是由著名詩人拜倫的女兒Ada設計的,因而她被公認為是第一個程序員。后來人們用她的名字命名為Ada語言。她對計算機的概念提出了許多深刻而影響深遠的見解。
2)最初的程序設計語言
20世紀50年代初,具有存儲程序的通用電子數(shù)字計算機問世。早期的程序是直接用二進制機器代碼編寫的。接著,很快就產生了能用符號和助記符表達機器代碼的匯編語言。
FORTRAN(FormulaTranslation)是第一個被廣泛用來進行科學計算的高級語言,在1954年至1957年間由JohnBackus領導下的IBM的一個開發(fā)小組研制出來。一個FORTRAN程序由一個主程序或一個主程序和若干子程序組成,主程序和子程序都是獨立的程序單位,稱為程序模塊。子程序是實現(xiàn)模塊化的有效途徑。FORTRAN也能用于通用程序設計,它的編譯程序效率較高,是一種影響比較深遠的程序設計語言,至今仍在某些科學應用領域發(fā)揮著重大的影響力。FORTRAN的一些特性已經成為語言的標準,如數(shù)組、由索引變量控制的循環(huán)結構、if分支語句等。
Algol60是于1958~1960年研制出來的一種用于科學研究和實際應用的通用程序設計語言。如果程序設計語言能夠應用于范圍廣泛的問題求解過程中,我們就稱之為通用程序設計語言。Algol60語言主導了20世紀60年代的程序語言的發(fā)展,它支持算法描述,在歐洲擁有眾多忠實的用戶。該語言具有嚴格的文法定義,采用巴克斯范式(BNF)來描述語言的語法,同時在程序設計中引進了許多概念,如自由格式、結構化語句、begin-end塊、變量類型說明、遞歸、傳值參數(shù)等。許多命令式語言都是由Algol60語言派生而來,如Pascal、C、Ada等。
COBOL(COmmonBusinessOrientedLanguage)是一種面向事務處理的高級語言,于1959~1960年由美國國防部的一個研制小組在GraceHopper的領導下研制出來。COBOL語言適用于數(shù)值計算并不復雜、數(shù)據(jù)處理的信息量卻很大的領域,比如企業(yè)管理。目前,COBOL語言主要應用于情報檢索、商業(yè)數(shù)據(jù)處理等領域。它的語法規(guī)則很嚴格,使用了300多個英語保留字,大量采用普通英語詞匯和句型。盡管COBOL語言語法復雜,但它仍不失為一種實用的語言,在相關領域的應用一直非常廣泛。以上三種高級語言是基于馮·諾依曼計算機體系結構標準創(chuàng)建的。有一些語言是在數(shù)學函數(shù)的基礎上開發(fā)的,如LISP和APL語言。
LISP(表處理器)是20世紀50年代末JohnMcCarthy設計的基于通用表結構及函數(shù)應用的語言。LISP多應用于人工智能領域,它引入了垃圾回收(或無用內存回收)等機制。APL是20世紀50年代末Harvard大學的K.?Iverson開發(fā)的一種程序設計語言。這種程序設計語言的運算能力強大,20世紀60年代初曾被IBM作為處理數(shù)組和矩陣等數(shù)學計算的程序設計語言。這兩種函數(shù)式語言也對后來的程序設計語言產生了極大的影響。
3)程序設計語言的迅速發(fā)展
自從最初的程序設計語言取得巨大成功后,越來越多的人都想涉及該領域,這直接導致了新的程序設計語言的大量涌現(xiàn)。這些語言盡管大多數(shù)現(xiàn)在已不復存在,但它們無疑極大地推動了程序設計語言的進一步發(fā)展和完善。20世紀60年代出現(xiàn)的語言中,影響比較大的主要有Simula67和BASIC。
Simula67由挪威的KristenNygaard和Ole-JohanDahl于1965~1967年研制出來。
Simula67最初是為了模擬離散事件而設計的,它的基本貢獻是對抽象和計算的理解,它引入了類的概念,這是大多數(shù)面向對象程序設計語言的基礎。Simula67被認為是第一個面向對象程序設計語言。
BASIC(BeginnersAll-purposeSymbolicInstructionCode)是由Dartmouth大學的JohnKemeney和ThomasKurtz于1964年設計的。BASIC最初是為分時系統(tǒng)而開發(fā)的一種簡單語言,隨后逐漸過渡到微型計算機領域,并且得到了廣泛的應用。ANSI分別于1978年和1988年頒布了BASIC的最簡標準和最高標準。
經過20世紀60年代的混戰(zhàn),語言設計者又重新開始考慮語言設計的簡單性和一致性問題。20世紀70年代的代表之作是Pascal語言和C語言。
Pascal語言是一種結構化程序設計語言,由瑞士蘇黎世聯(lián)邦工業(yè)大學的NiklausWirth教授研制,并于1971年正式發(fā)表。它將Algol語言的思想演化成為更適合于教學的簡潔、有效的結構化語言。一個Pascal程序可以看做一個操作系統(tǒng)調用的過程,而且其內部的過程還可以嵌套和遞歸。盡管Pascal語言比較簡單,并不具備足夠的實用特性,但它在教學和許多實際應用方面仍取得了很大的成就。
C語言是由貝爾實驗室于1972年設計出來的一種通用程序設計語言。C語言提供了一個豐富的運算符集合和比較緊湊的語句格式。C語言在許多方面比Pascal語言簡單,它簡化了類型系統(tǒng)和運行環(huán)境的復雜性,提供了更多訪問底層機器的途徑。C語言的主要特色是兼顧了高級語言和匯編語言的特點,簡潔、豐富、可移植。C語言的成功與操作系統(tǒng)緊密相關。它提供了高效的執(zhí)行語句,并且允許程序員直接訪問操作系統(tǒng)和底層硬件。廣泛流行的UNIX操作系統(tǒng)及其上的許多軟件都是用C語言編寫的。相對于高級語言,C語言有時也被稱為中級程序設計語言。
C++?語言是在C語言的基礎上發(fā)展起來的,與C語言兼容。它是1980年由貝爾實驗室開發(fā)出來的。C++?語言主要是在C語言的基礎上增加了類的機制,從而使其成為一種面向對象程序設計語言。它一開始也被稱為“含類庫的C”,增加了大容量的類庫等許多新特性,并具有較高的執(zhí)行效率。而且,由于C語言的流行和可移植,C++?語言事實上可以移植到任何平臺上運行。相關國際標準的制定更促進了C++?語言的廣泛應用。但是,由于C++已經成為一個龐大的語言系統(tǒng),反而顯得比較難以實現(xiàn)和徹底理解。
Java產生于20世紀90年代,它一開始被命名為Oak,是Sun公司的JamesGosling等人為嵌入式電子應用系統(tǒng)而開發(fā)的一種高級語言。隨著Internet應用的增長及Web的出現(xiàn),Sun的開發(fā)者們?yōu)檫m應Web和網絡應用,將其修改完善并定名為Java。Java主要是面向Internet應用的,但作為一種通用的程序設計語言,也得到了廣泛的應用。它保留了C++?的基本語法、類和繼承等概念,刪掉了C++?中一些不好的特征,是一種純粹的面向對象語言,其結構簡單、設計簡潔、可移植性好。與C++?相比,Java更加簡單,其語法和語義更加合理。如果只考慮通用語言而不考慮專用語言,則程序設計語言的發(fā)展過程可大致描述為如圖11.1所示的形態(tài)。面向機器程序設計語言是第一代程序設計語言,最初出現(xiàn)的程序設計語言是第二代程序設計語言,而結構化過程語言和面向對象語言則屬于第三代程序語言,第四代程序設計語言與以往的程序設計語言相比,將更加抽象和智能化。圖11.1程序設計語言的發(fā)展
2.程序設計語言的種類
程序設計語言的分類沒有統(tǒng)一的標準。根據(jù)程序設計語言的發(fā)展,大體上可以將其分為面向機器語言、高級語言和第四代語言三大類。
1)面向機器語言
面向機器語言依賴于具體的硬件結構,其語句與計算機的硬件操作相對應,主要是指二進制的機器語言和匯編語言。
2)高級語言
(1)基礎語言。高級語言創(chuàng)始于20世紀50年代。一開始的這些程序設計語言出現(xiàn)早、應用廣泛、有大量軟件庫,為早期的程序員廣泛接受和熟悉,所以稱為基礎語言。其中,BASIC、FORTRAN、COBOL、ALGOL是該類語言的代表。這些語言中有一些隨著版本的更新與性能的改進,至今仍被應用。
(2)結構化語言。結構化語言提供結構化的控制結構語句及數(shù)據(jù)類型定義語句,具有很強的過程描述能力和數(shù)據(jù)結構描述能力。它控制結構完備,數(shù)據(jù)結構和數(shù)據(jù)類型豐富,表達能力強,所編出來的程序模塊清晰,可移植性好。比較有代表性的結構化程序設計語言有Pascal、C等。
(3)面向對象語言。面向對象語言可以分為兩大類:一類是純面向對象語言,如Smalltalk、Eiffel、Java等;另一類是混合型面向對象語言,這類語言在面向過程語言的基礎上增加了面向對象的機制,如C++?等。成熟的面向對象語言通常都提供豐富的類庫和強有力的開發(fā)環(huán)境。純面向對象語言著重支持面向對象語言方法研究和快速原型的實現(xiàn);混合型面向對象語言一方面注重提高程序的運行速度,另一方面又要使得傳統(tǒng)的程序員能夠比較容易地接受面向對象的思想。
(4)專用語言。專用語言是為某種特殊應用而設計的程序設計語言,這類語言的應用范圍一般比較窄。例如,APL是為數(shù)組和向量運算而設計的語言,BLISS是為開發(fā)編譯程序和操作系統(tǒng)而設計的語言,L1SP和PROLOG兩種語言主要運用于人工智能領域。
3)第四代語言
也許有一天計算機有能力去理解人們用自然語言描述的軟件需求,這將極大地簡化軟件的開發(fā)工作。從程序設計語言的發(fā)展趨勢也可以看出,人們一直在不斷尋求使用越來越抽象的形式來表示程序,從而把程序員從復雜的過程性細節(jié)中解放出來。第四代語言(4GL)就是這樣一種語言,它在更高一級抽象的層次上表示程序結構和數(shù)據(jù)結構,不再需要規(guī)定算法的細節(jié),而由其語言系統(tǒng)運用專門的領域知識來填充過程細節(jié)。現(xiàn)有的第四代語言主要有數(shù)據(jù)庫查詢語言、程序生成器、判定支持語言、原型語言、形式化規(guī)格說明語言等。程序設計語言根據(jù)設計程序的辦法又可以分為命令式程序設計語言、面向對象程序設計語言、函數(shù)式程序設計語言和邏輯型程序設汁語言。
(1)命令式程序設計語言。命令式程序設計語言是一種基于動作的語言,它把計算看成是一種動作的序列。命令式程序設計語言開始于FORTRAN,其關鍵思想在Pascal和C語言中也得到了很好的體現(xiàn)。
(2)面向對象程序設計語言。面向對象程序設計語言將狀態(tài)和操作封裝于對象實體之中,并將具有相同狀態(tài)、操作和訪問機制的多個對象抽象成一個對象類。類是面向對象語言中必須提供的、由用戶定義的數(shù)據(jù)類型。面向對象語言具有繼承、封裝、多態(tài)等特征,有利于軟件的實現(xiàn)和重用。Smalltalk、C++、Java是面向對象程序設計語言的代表。
(3)函數(shù)式程序設計語言。函數(shù)式程序設計語言的基本概念來自于LISP語言,它是一類以λ演算為基礎的語言。LISP語言是1958年專門為人工智能的應用而設計的語言。在這種語言里,函數(shù)是一種映射規(guī)則,它使定義域中的每個元素和值中唯一的元素相對應,而且可以在一個函數(shù)定義里調用另一個函數(shù)。函數(shù)式程序設計語言的特點之一是,表達式中出現(xiàn)的任何函數(shù)都可以用其他函數(shù)來代替,只要這些函數(shù)調用產生相同的值。
(4)邏輯型程序設計語言。邏輯型程序設計語言是一類以形式邏輯為基礎的語言,以PROLOG語言為代表。PROLOG表示“ProgramminginLogic”,這種語言建立在關系理論和一階謂詞邏輯的基礎之上,和LISP語言一樣多用于人工智能領域。PROLOG程序是一系列事實、數(shù)據(jù)對象或事實間的具體關系和規(guī)則的集合。PROLOG語言的關鍵是模式匹配,通過匹配一組變量與預先定義好的模式和規(guī)則來完成操作。該語言具有很強的推理功能,適用于自動定理證明、自然語言理解及專家系統(tǒng)等。從語言的內在特點進行分類,則程序設計語言還可以分為系統(tǒng)實現(xiàn)語言、靜態(tài)語言、塊結構語言和動態(tài)語言四類。
(1)系統(tǒng)實現(xiàn)語言。系統(tǒng)實現(xiàn)語言從匯編語言發(fā)展而來,它提供高級語言功能,同時容許程序員直接針對計算機進行操作。C語言是一種系統(tǒng)實現(xiàn)語言。
(2)靜態(tài)語言。靜態(tài)語言的主要特點是靜態(tài)地分配存儲空間,這種存儲分配方式的優(yōu)點是方便編譯系統(tǒng)的設計和實現(xiàn),但相應地就給程序員增加了許多限制。比較著名的靜態(tài)語言有FORTRAN、COBOL等。
(3)塊結構語言。塊結構語言的特點是以程序塊為單位,提供一種有限形式的動態(tài)存儲分配。每當進入一個程序塊,就中斷程序的執(zhí)行,由存儲管理系統(tǒng)為其分配存儲空間,退出時則釋放該存儲空間。塊結構語言有PASCAL、ALGOL等。
(4)動態(tài)語言。動態(tài)語言支持動態(tài)存儲管理,這種語言在執(zhí)行個別語句的時候就可能引起存儲的分配和釋放。11.1.3程序設計語言的基本成分
1.數(shù)據(jù)
程序設計語言的數(shù)據(jù)成分對應程序設計語言里的數(shù)據(jù)類型。數(shù)據(jù)作為程序操作的對象,總是對應著應用系統(tǒng)中某些有意義的實體。數(shù)據(jù)具有名稱、類型、存儲類別、作用域和生存期等屬性,數(shù)據(jù)的表示指明了程序中值的組織形式,使用時要為數(shù)據(jù)分配存儲空間。
數(shù)據(jù)名稱是用戶命名的由字母、數(shù)字和下劃線組成的標識符。數(shù)據(jù)類型說明數(shù)據(jù)占用內存空間的大小和存儲形式。存儲類別說明數(shù)據(jù)在內存中的位置和生存期。作用域說明數(shù)據(jù)的作用范圍,即可以使用數(shù)據(jù)的代碼范圍。生存期說明數(shù)據(jù)占用內存空間的時間。
(1)常量和變量。常量的值在程序運行時不能改變,變量的值在程序運行時可以改變。程序中的數(shù)據(jù)對象在內存中表現(xiàn)為存儲單元的地址和內容,分別對應于數(shù)據(jù)對象的左值和右值。當數(shù)據(jù)的值改變時,實際上改變的是數(shù)據(jù)對象的右值。
(2)全局量和局部量。全局量和局部量的區(qū)別主要是數(shù)據(jù)作用域的范圍不同。在程序運行過程中,系統(tǒng)為全局變量分配的存儲空間一般是不改變的,而為局部變量分配的存儲空間則是動態(tài)改變的。
(3)數(shù)據(jù)類型。數(shù)據(jù)類型一般可以分為基本類型、構造類型、用戶自定義類型等。數(shù)據(jù)類型不同,數(shù)據(jù)的組織形式也會有所區(qū)別。
在C++?語言里,基本數(shù)據(jù)類型包括整型(int)、字符型(char)、實型(float、double)和布爾型(bool)。指針類型(type*)是一種比較常用的數(shù)據(jù)類型??疹愋?void)是一種特殊類型。枚舉類型(enum)是一種用戶自定義類型。而構造類型包括數(shù)組、結構和聯(lián)合。另外,類類型是一種抽象數(shù)據(jù)類型。
2.運算
程序設計語言的運算成分主要包括運算符號和運算規(guī)則的規(guī)定。高級語言的運算一般可分為數(shù)值運算、關系運算和邏輯運算。運算符號的使用與數(shù)據(jù)類型密切相關,而且要規(guī)定優(yōu)先級和結合性,以確保運算結果的唯一性。
3.控制
程序語言的控制成分是指程序語言所允許表述的控制結構。理論證明,可計算問題的程序都可以用順序結構、選擇結構和循環(huán)結構來描述。
(1)順序結構。順序結構用來表示一個順序計算操作序列。用順序結構表述的計算過程從執(zhí)行第一個操作開始,按順序依次執(zhí)行所有后續(xù)操作,直至該執(zhí)行序列的最后一個操作。順序結構示意圖如圖11.2所示。
順序結構在C++?里可以表現(xiàn)為復合語句,也就是由“{”和“}”括起來的程序語句。復合語句在程序中作為一個整體來執(zhí)行。圖11.2順序結構
(2)選擇結構。選擇結構提供了在兩個或多個分支中選擇其中一個或多個的邏輯。選擇結構在程序設計語言中用條件語句來實現(xiàn)。選擇結構首先需要指定一個條件,根據(jù)條件的成立與否決定控制流走向哪一個程序分支,其示意圖如圖11.3所示。選擇結構可以嵌套其他結構及其自身。簡化的選擇結構可以沒有程序塊B,即:如果條件成立,則執(zhí)行A;如果條件不成立,則什么也不做。圖11.3選擇結構在C++?里選擇結構用if語句和switch語句實現(xiàn)。
if語句的一般形式為:
if(表達式)語句lelse語句2
當語句2為空時,可以簡化為:
if(表達式)語句1
if語句是一種雙分支結構,當表達式成立時,執(zhí)行語句1;當表達式不成立時,執(zhí)行語句2或什么也不執(zhí)行。執(zhí)行switch語句時,首先計算表達式的值,將其與所列舉的常量表達式的值比較。如果匹配,則執(zhí)行后面的語句;如果該值與所有的常量表達式的值都無法匹配,則執(zhí)行default后面的語句??梢允褂胋reak跳出switch語句。
(3)循環(huán)結構。循環(huán)結構描述了重復計算的過程。循環(huán)結構通常包括三部分:初始化、循環(huán)條件和循環(huán)體。初始化是在進入循環(huán)體之前,對在循環(huán)體中所要用到的變量賦初值,有時并不需要顯式表示。循環(huán)條件是程序重復執(zhí)行所必須滿足的約束條件。循環(huán)體是重復計算的內容。循環(huán)結構主要有兩種形式。一種是先判斷條件是否成立,如果成立則執(zhí)行循環(huán)體,然后再次判斷循環(huán)條件是否滿足,而進一步確定是否進入下一次循環(huán),這稱為while型循環(huán)結構。另一種是do-while型循環(huán)結構,它的執(zhí)行過程是:先進入循環(huán)體執(zhí)行程序塊,然后判斷條件是否成立,如果條件成立則繼續(xù)執(zhí)行循環(huán)體,進入下一次循環(huán)判斷,否則停止執(zhí)行,退出循環(huán)結構。顯然,與while型循環(huán)結構不同的是,do-while型循環(huán)結構先執(zhí)行一次循環(huán)體,然后再對循環(huán)條件進行判斷,也就是說,在do-while型循環(huán)結構里,循環(huán)體至少要被執(zhí)行一次。循環(huán)結構的示意圖分別如圖11.4和圖11.5所示。圖11.4while型循環(huán)結構圖11.5do-while型循環(huán)結構函數(shù)首部包含函數(shù)的返回值類型、函數(shù)名以及函數(shù)運行所需要的參數(shù)及其類型。函數(shù)體包含實現(xiàn)函數(shù)功能的程序語句。另外,C++?程序中所有函數(shù)的定義都是獨立的,不允許函數(shù)的嵌套定義。函數(shù)的使用也要遵循先聲明后使用的原則。如果對函數(shù)的調用在函數(shù)定義之前,則應先聲明函數(shù)。函數(shù)聲明的一般格式如下:
返回值類型函數(shù)名(形式參數(shù)表);
函數(shù)聲明定義了函數(shù)的原型,規(guī)定了傳遞給函數(shù)的參數(shù)個數(shù)、參數(shù)類型以及函數(shù)返回值類型。編譯器可以據(jù)此對函數(shù)的調用進行初步檢查,以確定調用是否正確。函數(shù)聲明必須與函數(shù)定義一致。函數(shù)調用只需知道被調用函數(shù)所能實現(xiàn)的功能以及函數(shù)調用的方法,而無需關心函數(shù)實現(xiàn)的內部細節(jié)。函數(shù)調用的一般形式為:
函數(shù)名(實際參數(shù)表);
可見,要調用一個函數(shù),需知道該函數(shù)的函數(shù)名、傳遞的參數(shù)(個數(shù)、類型和順序)等信息。函數(shù)間的信息交換主要是靠返回值及參數(shù)傳遞來實現(xiàn)。使用返回值時,被調函數(shù)執(zhí)行以后,把結果返回給主調函數(shù)。參數(shù)傳遞時實參與形參的信息交換方法主要有傳值調用和引用調用兩種。傳值調用時,實參向形參傳遞相應類型的值,函數(shù)對所傳遞的值進行運算,但不能向實參返回任何信息。通常可以使用指針作為形參,這樣,當函數(shù)調用時,首先對實參進行取地址運算,將實參地址傳遞給形參,從而實現(xiàn)對實參的修改。這是一種間接內存訪問形式。
引用調用時,將實際參數(shù)的地址傳遞給形式參數(shù),使得形參的地址就是對應的實參的地址。這時候,形參相當于是實參的別名,函數(shù)中對形參的訪問和修改也就相當于對相應的實際參數(shù)所作的訪問和修改。一個類類型中可以有兩種成員:數(shù)據(jù)和操作,它們在C++?語言中被稱為數(shù)據(jù)成員和成員函數(shù)。根據(jù)它們的被訪問權限,類的成員又可以分為私有段成員、保護段成員和公有段成員,分別對應于段約束符private、protected和public。其中,private標識的部分為私有段,它們只能被類的成員函數(shù)所訪問,private標識符可以缺省;由protected標識的部分為保護段,它們能被本類及其派生類的成員函數(shù)所訪問;由public標識的部分為公有段,它們可以被其他類的對象所訪問,構成該類類型對象的訪問接口。另外,在類里,定義公有和私有成員的順序可以是任意的。11.1.4程序設計語言的要素
1.命名約定
名字的聲明,即預先說明程序中使用的對象的名字。某些程序設計語言要求“先聲明、后使用”,如C語言。這樣就使得編譯程序能檢查程序中所出現(xiàn)的名字的合法性,從而幫助程序員發(fā)現(xiàn)和改正程序中的錯誤。也有一些程序設計語言,如FORTRAN和BASIC,并不要求用戶顯式地說明程序中所有對象的名字,當?shù)谝淮问褂靡粋€名字來表示一個對象時,則自動地被編譯系統(tǒng)看做是對該對象的名字的聲明。這樣表面上看起來使用非常方便,但實際上更加容易出錯。在輸入源程序時,如果程序員輸入了錯誤的對象名字,這時候它最有可能將被編譯系統(tǒng)理解為新定義的對象,而不會報告錯誤,這樣造成的程序錯誤是很難發(fā)現(xiàn)的,特別是當輸入錯誤的字符和預定要使用的字符非常相像(如字母o和數(shù)字0,字母l和數(shù)字1等)的時候。因此,現(xiàn)在盡管有一些程序設計語言(如VBScript腳本語言)并不要求顯式說明其所用到的對象的名字,但我們應盡可能地遵循“先聲明,后使用”的約定。
2.類型說明
類型說明與名字的聲明緊密相聯(lián),一般在聲明對象名字的同時說明對象的類型。在名字聲明的時候,通過類型說明,用戶定義了對象的類型,從而確定了該對象的使用方式和存儲方式。這樣,編譯系統(tǒng)就能夠在編譯時發(fā)現(xiàn)對一個特定類型對象的使用是否合法,從而減少程序錯誤。規(guī)定必須在使用前預先說明對象的類型,使對象的定義更加明確,也有助于減少閱讀程序時的歧義性。有些程序設計語言允許用戶不對變量的類型進行顯式的說明,給程序的安全性留下了隱患。程序設計語言中的類型說明不僅僅是一種安全措施,也是一種重要的抽象機制。為了適應軟件設計和編程的需要,某些程序設計語言(如Pascal等)還允許程序員在程序設計過程中定義與特定應用有關的自己的數(shù)據(jù)類型。用戶既可以定義整型、字符型等簡單類型,也可以定義鏈表、二叉樹等復雜的結構類型。面向對象的程序設計語言中的類,從本質來說,也是一種由用戶自定義的數(shù)據(jù)結構類型。它允許把各種數(shù)據(jù)類型及對其進行的操作封裝成一個整體(即類),供程序使用。對類型名字的定義使得我們可以引用某些復雜的實體,而不必考慮這些實體的表示方法。
3.變量初始化
在使用變量前沒有對變量進行初始化是程序中最常見的錯誤之一。最有效地減少程序發(fā)生錯誤的方法是,在聲明變量時對程序中的所有變量進行初始化。但大多數(shù)程序設計語言通常都無法對此進行檢查和約束,更沒有辦法強制程序員一定要這樣做。以下是一個有效的解決辦法:聲明變量時,如果尚未初始化,首先由系統(tǒng)給變量賦一個標明變量還沒被初始化的特殊的值,以后如果沒有對這個變量賦值就企圖利用它的值,則系統(tǒng)應能發(fā)出出錯信號,以提示用戶對該變量進行有效的初始化。
4.程序對象局部化
程序對象局部化是程序設計的一個一般原理。程序對象的名字應該在靠近使用它們的地方引入,并且在程序真正需要它們的地方才具有可見性(即可訪問它們)。程序設計語言的局部性按其提供局部變量的途徑可分為單層局部性和多層局部性。如FORTRAN等語言提供的是單層局部性,塊結構語言提供的是多層局部性。
多層次的局部性有助于提高程序的可讀性。如果程序對象名字的特性在靠近使用這些名字的地方進行說明,程序的閱讀者就能很容易地獲得有關這些名字的信息。多層次局部性也有助于減少程序中所存在的差錯和提高程序的可修改性。具有多層次局部性的程序設計語言通常鼓勵程序員盡量使用局部的對象。在塊結構語言中,如果內層結構和外層結構使用了相同的變量名,那么外層名字在內層是不可見的,內層不能訪問外層的同名變量。這樣一方面給程序的編寫提供了方便,另一方面也往往會由于疏忽而引起錯誤。特別是在程序維護時,如果維護人員不是程序的設計人員,則更容易出現(xiàn)這種差錯。使用具有單層局部性的程序設計語言寫出來的程序可讀性要差一些,但是卻容易實現(xiàn)程序單元的獨立編譯。
5.程序模塊
在塊結構語言中,在較內層程序塊中說明的名字不能被較外層的程序塊訪問,這是塊結構語言控制程序對象名字可見性的主要手段。由于是動態(tài)存儲分配,當調用完一個程序模塊時,局部對象的值當即被釋放,如果需要在多次調用這些子程序的過程中保存和傳遞對象的值,則須把對象說明成全局的,也就是程序中所有的子程序都可以訪問。程序模塊之間的數(shù)據(jù)共享可以通過定義全局變量來提供,然而這卻降低了程序的安全性,同時也增加了程序維護時發(fā)生錯誤的可能性。有些語言(如C、C++?語言等)通過靜態(tài)變量提供共享,這就很好地解決了這個問題。
6.循環(huán)控制結構
循環(huán)控制結構通??梢苑譃槿N情況。一種是給定循環(huán)次數(shù),當計數(shù)結束時即結束循環(huán)。還有一種是在每次進入循環(huán)體之前測試循環(huán)結束條件,根據(jù)該條件決定是結束循環(huán)還是進入下一輪循環(huán)。又或者每執(zhí)行完一次循環(huán)體測試一次循環(huán)結束條件,以判斷是否結束循環(huán)。在實際應用中,有時還需要在循環(huán)體內任意一點測試循環(huán)結束條件,以做出相應處理,如提前跳出循環(huán)。在C或C++?語言中,循環(huán)控制結構可以用for語句、while語句和do-while語句表示。在循環(huán)體內可以使用break語句或continue語句,或跳出循環(huán),或忽略循環(huán)體的執(zhí)行而直接進入下一次循環(huán)。在C語言中還提供了goto語句,以實現(xiàn)程序控制流的跳轉,但由于它會破壞程序的邏輯結構,因此在程序設計中并不提倡使用。
7.分支控制結構
分支控制結構是一種選擇結構,在兩種或多種分支中,根據(jù)程序所提供的條件的滿足情況選擇其中的一個或多個邏輯。分支控制結構在程序設計語言中通常有if型和case型。if語句比較簡單,常用在分支比較少的情況下。多分支的case語句則可能會存在以下一些問題。如果case表達式的取值不在預先定義的范圍內,則無法決定程序應該做的動作。在某些程序設計語言中,case表達式選定執(zhí)行的語句與所有可能執(zhí)行的case語句的排列次序有關,如果語句的次序不正確,則可能會出現(xiàn)意想不到的結果,而且系統(tǒng)編譯和運行時并不能發(fā)現(xiàn)此類錯誤。在C或C++?語言中,只有當case表達式的值與case標號相匹配,才選擇相應的語句來執(zhí)行,case中沒有定義的情況,則在default標號下進行處理,這樣即很好地解決了以上問題。
8.異常處理
異常是指程序運行過程中發(fā)生的錯誤或意外事件,程序必須對此類事件做出必要的處理,否則將導致程序的中斷和其他意想不到的后果。多數(shù)程序設計語言在檢測和處理異常方面給程序員提供的幫助非常之少,程序員只能使用語言提供的一般控制結構檢測異常,當發(fā)生異常時,把控制轉移到處理異常的程序段。這樣,當程序中包含一系列子程序的嵌套調用時,需要把出現(xiàn)的異常信息從一個子程序傳送到另外的子程序,但是要完成此任務并沒有方便而又可靠的方法。而且,使用一般控制結構來判斷和處理異常,需要明顯增加程序長度并且使程序的邏輯變得繁瑣難懂。有些程序設計語言提供了比較完善的異常處理機制,如Java語言。
9.獨立編譯
獨立編譯是指能分別編譯各個程序單元,然后再把它們集成為一個完整的程序。一個大程序往往由許多不同的程序單元(如過程、函數(shù)、子程序或模塊等)組成。如果每修改其中任何一個程序單元,都需要重新編譯整個程序,那么程序開發(fā)、調試和維護的成本將會大大增加。如果該程序設計語言支持各個程序的獨立編譯,則只需要重新編譯經過修改了的程序單元,然后重新連接整個程序即可。顯然,一個具有獨立編譯機制的程序設計語言是比較適合于軟件工程需要的。11.1.5編程語言的選擇
當軟件開發(fā)成為一種工程化生產,程序編碼也不再是程序員個人的事,而需要許多程序員同心協(xié)力地投入才能勝任。在編碼前必須確定程序設計的方法,把大的軟件開發(fā)任務細化,然后每個程序員才能同時進行自己所要完成的工作。
不同的編程語言有著不同的優(yōu)點,也有著它們不足的地方。目前在計算機上的程序設計語言越來越多,給程序員提供了更多選擇的機會。開始時程序員一般選擇自己熟悉的語言,但如果設計者能根據(jù)實際需要選擇合適的程序語言,將使編碼及代碼維護更容易,測試工作量也會減少。由于軟件系統(tǒng)的絕大部分成本用在生命周期的測試和維護階段,所以易于測試和維護是選擇程序設計語言的重要因素??偟貋碚f,理想的程序設計語言應該具有良好的模塊化機制,良好的控制結構、數(shù)據(jù)結構和數(shù)據(jù)安全性,較好的可讀性、可移植性和可維護性,較完備的開發(fā)工具和開發(fā)環(huán)境,良好的編譯調試系統(tǒng)和獨立編譯機制,等等。
具體來說,編程語言的選擇一般應遵循以下幾點標準。
1.語言的適用領域
不同的語言都有其自己的適用領域。在科學與工程計算領域方面,F(xiàn)ORTRAN語言、Pascal等最為常用。在數(shù)據(jù)庫、信息系統(tǒng)方面,SQL、Oracle、FoxPro都是適用的語言,而SQL較為常用。實時應用系統(tǒng)要求有很快的響應速度,此時可選用匯編語言、Ada語言或C語言等。在網絡應用中,Java是較為合適的語言??傊绦騿T應根據(jù)不同語言的特點,結合所要開發(fā)的軟件,選擇最為適合的語言。
2.軟件的運行環(huán)境
最終軟件運行的硬件及軟件環(huán)境也是影響語言選擇的因素,要確保軟件能運行于所處的環(huán)境中。開發(fā)出來的軟件系統(tǒng)必須具有可用性,這是用戶的必然要求。計算機操作系統(tǒng)之間的不兼容,使其成為軟件開發(fā)中必須考慮的一大因素。如果軟件需要運行在Windows操作系統(tǒng)下,則最好選擇適合在Windows配置和運行的開發(fā)工具;如果軟件要運行在UNIX/Linux下,就應該選擇適合在UNIX/Linux環(huán)境下使用的開發(fā)工具;而從軟件的體系結構來說,如果軟件運行在Web/Browser結構下,就需要選擇ASP/JSP等腳本語言來編寫動態(tài)網頁。
3.系統(tǒng)用戶的要求
如果所開發(fā)的系統(tǒng)是由用戶自己來維護的,則應該選擇用戶較為熟悉的語言來編寫程序。系統(tǒng)使用和維護的周期相對較長,因而這個要求具有一定的合理性。
4.算法和數(shù)據(jù)結構的復雜程度
科學計算、人工智能領域方面的問題算法比較復雜,數(shù)據(jù)庫應用、數(shù)據(jù)處理方面的算法比較簡單,在選擇編程語言時要考慮某種語言是否能滿足算法的復雜程度。
5.兼容性和移植性
不同機器上能執(zhí)行的語言可能不同,程序員還應考慮硬件設備對語言的兼容性。同時如果將來要把開發(fā)軟件移植的話,還要考慮編程語言的移植性問題,使開發(fā)軟件能移植到不同的硬件環(huán)境下運行。
6.軟件開發(fā)方法
有些編程語言依賴于開發(fā)的方法。如果是過程化程序開發(fā)方法,宜采用過程化程序設計語言;若是面向對象的開發(fā)方法,則應采用面向對象的程序設計語言。軟件開發(fā)方法的選擇應適合具體的應用。
7.軟件系統(tǒng)開發(fā)的規(guī)模
若開發(fā)的系統(tǒng)規(guī)模較大,對于一些設計語言不能適用,那么就要找出一種能承擔如此大的系統(tǒng)規(guī)模的編程語言。有時候設計并實現(xiàn)一種供特定類工程項目專用的程序設計語言,可能也會是一個很好的選擇。
8.程序設計人員的技術水平
選擇編程語言時,還要考慮程序設計人員的知識以及技術水平。如果程序員不能對某種語言熟練地掌握以及沒有實踐的經驗,是不能很好地用這種語言編寫好程序的。雖然對于有經驗的程序員來說,學習一種新的程序設計語言并不難,但是要完全掌握一種新語言卻需要一定的實踐。已有的語言已經積累了大量的久經使用的程序,具有比較完整的資料、支撐軟件和軟件開發(fā)工具,而且有過類似項目的開發(fā)經驗和成功先例,顯然這些都可以大大降低軟件開發(fā)的工作量和日常維護工作的困難程度。熟悉的語言,使開發(fā)人員對于項目的成功更加有信心。所以,選擇一種程序員都熟悉的語言,對于軟件的開發(fā)無疑是事半功倍的。11.1.6面向對象語言的優(yōu)點
面向對象設計的結果既可以用面向對象語言實現(xiàn),也可以用非面向對象語言實現(xiàn)。使用面向對象語言時,由于語言本身充分支持面向對象概念的實現(xiàn),因此,編譯程序可以自動把面向對象概念映射到目標程序中。使用非面向對象語言編寫面向對象程序,則必須由程序員自己把面向對象概念映射到目標程序中。例如,C語言并不直接支持類或對象的概念,程序員只能在結構(struct)中定義變量和相應的函數(shù)(事實上,不能直接在結構中定義函數(shù)而是要利用指針間接定義)。所有非面向對象語言都不支持一般—特殊結構的實現(xiàn),使用這類語言編程時要么完全回避繼承的概念,要么在聲明特殊化類時,把對一般化類的引用嵌套在它里面。到底應該選用面向對象語言還是非面向對象語言,關鍵并不在于語言功能的強弱。從原理上說,使用任何一種通用語言都可以實現(xiàn)面向對象概念。當然,使用面向對象語言實現(xiàn)面向對象概念,遠比使用非面向對象語言方便。但是,方便性也并不是決定選擇何種語言的關鍵因素。選擇編程語言的關鍵因素是語言的一致的表式方法、可重用性及可維護性。從面向對象觀點看來,能夠更完整、更準確地表達問題域語義的面向對象語言的語法是非常重要的,因為這會帶來下述幾個重要優(yōu)點。
1.一致的表示方法
從前面章節(jié)的講述中可以知道,面向對象開發(fā)基于不隨時間變化的、一致的表示方法。這種表示方法應該從問題域到面向對象分析(OOA),從OOA再到面向對象設計(OOD),最后從OOD到面向對象編程(OOP),始終穩(wěn)定不變。一致的表示方法既有利于在軟件開發(fā)過程中始終使用統(tǒng)一的概念,也有利于維護人員理解軟件的各種配置成分。
2.可重用性
為了能帶來可觀的商業(yè)利益,必須在更廣泛的范圍中運用重用機制,而不是僅僅在程序設計這個層次上進行重用。因此,在OOA、OOD直到OOP中都顯式地表示了問題域語義,其意義是十分深遠的。隨著時間的推移,軟件開發(fā)組織既可能重用它在某個問題域內的OOA結果,也可能重用相應的OOD和OOP結果。
3.可維護性
盡管人們反復強調保持文檔與源程序一致的必要性,但是,在實際工作中很難做到交付兩類不同的文檔,并使它們保持彼此完全一致。特別是考慮到進度、預算、能力和人員等限制因素時,做到兩類文檔完全一致幾乎是不可能的。因此,維護人員最終面對的往往只有源程序本身。
讓我們以ATM系統(tǒng)為例,說明在程序內部表達問題域語義對維護工作的意義。假設在維護該系統(tǒng)時沒有合適的文檔資料可供參閱,于是維護人員人工瀏覽程序或使用軟件工具掃描程序,記下或打印出程序顯式陳述的問題域語義。維護人員看到“ATM”、“賬戶”和“現(xiàn)金兌換卡”等,這對維護人員理解所要維護的軟件將有很大幫助。因此,在選擇編程語言時應該考慮的首要因素是,在供選擇的語言中哪個語言能最好地表達問題域語義。一般來說,應該盡量選用面向對象語言來實現(xiàn)面向對象分析、設計的結果。
11.1.7面向對象語言的技術特點
面向對象語言的形成借鑒了歷史上許多程序語言的特點,從中吸取了豐富的營養(yǎng)。當今的面向對象語言從20世紀50年代誕生的LISP語言中引進了動態(tài)聯(lián)編的概念和交互式開發(fā)環(huán)境的思想,從60年代推出的SIMULA語言中引進了類的概念和繼承機制。此外,它還受到70年代末期開發(fā)的Modula-2語言和Ada語言中數(shù)據(jù)抽象機制的影響。
20世紀80年代以來,面向對象語言像雨后春筍一樣大量涌現(xiàn),形成了兩大類面向對象語言。一類是純面向對象語言,如Smalltalk和Eiffel等語言;另一類是混合型面向對象語言,也就是在過程語言的基礎上增加了面向對象機制的語言,如C++?等語言。
一般來說,純面向對象語言著重支持面向對象方法的研究和快速原型的實現(xiàn),而混合型面向對象語言的目標則是提高運行速度和使傳統(tǒng)程序員容易接受面向對象思想。成熟的面向對象語言通常都提供豐富的類庫和強有力的開發(fā)環(huán)境。
下面介紹在選擇面向對象語言時應該著重考察的一些技術特點。
1.支持類與對象概念的機制
所有面向對象語言都允許用戶動態(tài)創(chuàng)建對象,并且可以用指針引用動態(tài)創(chuàng)建的對象。允許動態(tài)創(chuàng)建對象,就意味著系統(tǒng)必須處理內存管理問題,如果不及時釋放不再需要的對象所占用的內存,動態(tài)存儲分配就有可能耗盡內存。
有兩種管理內存的方法:一種是由語言的運行機制自動管理內存,即提供自動回收“垃圾”的機制;另一種是由程序員編寫釋放內存的代碼。自動管理內存不僅方便而且安全,但是必須采用先進的垃圾收集算法才能減少開銷。某些面向對象的語言(如C++)允許程序員定義析構函數(shù)(destructor)。每當一個對象超出范圍或被顯式刪除時,就自動調用析構函數(shù)。這種機制使得程序員能夠方便地構造和喚醒釋放內存的操作,卻又不是垃圾收集機制。
2.實現(xiàn)整體—部分結構的機制
一般來說,有兩種方法——指針和獨立的關聯(lián)對象可實現(xiàn)整體—部分結構。大多數(shù)現(xiàn)有的面向對象語言并不顯式支持獨立的關聯(lián)對象。在這種情況下,使用指針是最容易的實現(xiàn)方法,通過增加內部指針可以方便地實現(xiàn)關聯(lián)。
3.實現(xiàn)一般—特殊結構的機制
一般—特殊結構的機制既包括實現(xiàn)繼承的機制也包括解決名字沖突的機制。所謂解決名字沖突,指的是處理在多個基類中可能出現(xiàn)的重名問題。這個問題僅在支持多重繼承的語言中才會遇到。某些語言拒絕接受有名字沖突的程序,另一些語言提供了解決沖突的協(xié)議。不論使用何種語言,程序員都應該盡力避免出現(xiàn)名字沖突。
4.實現(xiàn)屬性和服務的機制
對于實現(xiàn)屬性的機制,應該著重考慮以下幾個方面:支持實例連接的機制;屬性的可見性控制;對屬性值的約束。對于服務來說,主要應該考慮下列因素:支持消息連接(即表達對象交互關系)的機制;控制服務可見性的機制;動態(tài)聯(lián)編。
所謂動態(tài)聯(lián)編,是指應用系統(tǒng)在運行過程中執(zhí)行一個特定服務時,選擇(或聯(lián)編)實現(xiàn)該服務的適當算法的能力。動態(tài)聯(lián)編機制使得程序員在向對象發(fā)送消息時擁有較大的自由,在發(fā)送消息前,無須知道接受消息的對象當時屬于哪個類。
5.類型檢查
程序設計語言可以按照編譯時進行類型檢查的嚴格程度來分類。如果語言僅要求每個變量或屬性隸屬于一個對象,則是弱類型的;如果語法規(guī)定每個變量或屬性必須準確地屬于某個特定的類,則這樣的語言是強類型的。面向對象語言在這方面差異很大,例如,Smalltalk實際上是一種無類型語言(所有變量都是未指定類的對象);C++和Eiffel則是強類型語言?;旌闲驼Z言(如C++、Objective_C等)甚至允許屬性值不是對象而是某種預定義的基本類型數(shù)據(jù)(如整數(shù)、浮點數(shù)等),以可以提高操作的效率。強類型語言主要有兩個優(yōu)點:一是有利于在編譯時發(fā)現(xiàn)程序錯誤,二是增加了優(yōu)化的可能性。通常使用強類型編譯型語言開發(fā)軟件產品,使用弱類型解釋型語言快速開發(fā)原型。總地來說,強類型語言有助于提高軟件的可靠性和運行效率?,F(xiàn)代的程序語言理論支持強類型檢查,大多數(shù)新語言都是強類型的。
6.類庫
大多數(shù)面向對象語言都提供一個實用的類庫。某些語言本身并沒有規(guī)定提供什么樣的類庫,而是由實現(xiàn)這種語言的編譯系統(tǒng)自行提供類庫。因存在類庫,許多軟構件就不必由程序員重頭編寫了,這為實現(xiàn)軟件重用帶來了很大方便。
類庫中往往包含實現(xiàn)通用數(shù)據(jù)結構(例如動態(tài)數(shù)組、表、隊列、棧和樹等)的類,通常把這些類稱為包容類。在類庫中還可以找到實現(xiàn)各種關聯(lián)的類。
更完整的類庫通常還提供獨立于具體設備的接口類(例如輸入/輸出流)。此外,用于實現(xiàn)窗口系統(tǒng)的用戶界面類也非常有用,它們構成了一個相對獨立的圖形庫。
7.效率
許多人認為面向對象語言的主要缺點是效率低。產生這種印象的一個原因是,某些早期的面向對象語言是解釋型的而不是編譯型的。事實上,使用擁有完整類庫的面向對象語言,有時能比使用非面向對象語言得到運行更快的代碼,這是因為類庫中提供了更高效的算法和更好的數(shù)據(jù)結構。例如,程序員已經無須編寫實現(xiàn)哈希表或平衡樹算法的代碼,類庫中已經提供了這類數(shù)據(jù)結構,而且算法先進,代碼精巧可靠。
認為面向對象語言效率低的另一個理由,是說這種語言在運行時使用動態(tài)聯(lián)編實現(xiàn)多態(tài)性,這似乎需要在運行時查找繼承樹,以定義給定操作的類。事實上,絕大多數(shù)面向對象語言都優(yōu)化了這個查找過程,從而實現(xiàn)了高效率查找。只要在程序運行時始終保持類結構不變,就能在子類中存儲各個操作的正確入口點,從而使得動態(tài)聯(lián)編成為查找哈希表的高效過程,不會由于繼承樹深度加大或類中定義的操作數(shù)增加而降低效率。
8.持久保存對象
任何應用程序都對數(shù)據(jù)進行處理,如果希望數(shù)據(jù)能夠不依賴于程序執(zhí)行的生命期而長時間保存下來,則需要提供某種保存數(shù)據(jù)的方法。希望長期保存數(shù)據(jù)主要出于以下兩個原因:
●為實現(xiàn)在不同程序之間傳遞數(shù)據(jù),需要保存數(shù)據(jù);
●為恢復被中斷了的程序的運行,首先需要保存數(shù)據(jù)。一些面向對象語言(例如C++)沒有提供直接存儲對象的機制。這些語言的用戶必須自己管理對象的輸入/輸出,或者購買面向對象的數(shù)據(jù)庫管理系統(tǒng)。
另外一些面向對象語言(例如Smalltalk)把當前的執(zhí)行狀態(tài)完整地保存在磁盤上。還有一些面向對象語言提供了訪問磁盤對象的輸入/輸出操作。
通過在類庫中增加對象存儲管理功能,可以在不改變語言定義或不增加關鍵字的情況下,就在開發(fā)環(huán)境中提供這種功能。然后,可以從“可存儲的類”中派生出需要持久保存的對象,該對象自然繼承了對象存儲管理功能。這就是Eiffel語言采用的策略。
理想情況下,應該使程序設計語言語法與對象存儲管理語法實現(xiàn)無縫集成。
9.參數(shù)化類
在實際的應用程序中,常??吹竭@樣一些軟件元素(即函數(shù)、類等軟件成分),從它們的邏輯功能看,彼此是相同的,所不同的主要是處理的對象(數(shù)據(jù))的類型不同。例如,對于一個向量(一維數(shù)組)類來說,不論是整型向量、浮點型向量,還是其他任何類型的向量,針對它的數(shù)據(jù)元素所進行的基本操作都是相同的(例如插入、刪除、檢索等)。當然,不同向量的數(shù)據(jù)元素的類型是不同的。如果程序語言提供一種能抽象出這類共性的機制,則對減少冗余和提高可重用性是大有好處的。所謂參數(shù)化類,就是使用一個或多個類型去參數(shù)化一個類的機制。有了這種機制,程序員就可以先定義一個參數(shù)化的類模板(即在類定義中包含以參數(shù)形式出現(xiàn)的一個或多個類型),然后把數(shù)據(jù)類型作為參數(shù)傳遞進來,從而把這個類模板應用在不同的應用程序中,或用在同一應用程序的不同部分。Eiffel語言中就有參數(shù)化類,C++?語言也提供了類模板。
10.開發(fā)環(huán)境
軟件工具和軟件工程環(huán)境對軟件生產率有很大影響。由于面向對象程序中的繼承關系和動態(tài)聯(lián)編等引入了特殊復雜性,面向對象語言所提供的軟件工具或開發(fā)環(huán)境就顯得尤其重要了。至少應該包括下列一些最基本的軟件工具:編輯程序、編譯程序或解釋程序、瀏覽工具和調試器(debugger)等。
編譯程序或解釋程序是最基本、最重要的軟件工具。編譯與解釋的差別主要是速度和效率不同。利用解釋程序解釋執(zhí)行用戶的源程序,雖然速度慢、效率低,但卻可以更方便、更靈活地進行調試。編譯型語言適用于開發(fā)正式的軟件產品,優(yōu)化工作做得好的編譯程序能生成效率很高的目標代碼。有些面向對象語言(例如Objective_C)除提供編譯程序外,還提供一個解釋工具,從而給用戶帶來很大方便。某些面向對象語言的編譯程序先把用戶源程序翻譯成一種中間語言程序,然后再把中間語言程序翻譯成目標代碼。這樣做可能會使得調試器不能理解原始的源程序。在評價調試器時,首先應該弄清楚它是針對原始的面向對象源程序,還是針對中間代碼進行調試的。如果是針對中間代碼進行調試的,則會給調試人員帶來許多不便。此外,面向對象的調試器應該能夠查看屬性值和分析消息連接的后果。
在開發(fā)大型系統(tǒng)的時候,需要有系統(tǒng)構造工具和變動控制工具。因此應該考慮語言本身是否提供了這種工具,或者該語言能否與現(xiàn)有的這類工具很好地集成起來。經驗表明,傳統(tǒng)的系統(tǒng)構造工具(例如UNIX的Make)目前對許多應用系統(tǒng)來說都已經太原始了。
11.2編碼規(guī)范
一個軟件質量的好壞不僅跟程序設計的語言有關,還與程序設計的規(guī)范與風格有著緊密的關系。程序員應當掌握適當?shù)木幊碳记?,形成統(tǒng)一的編程風格,建立良好的編程習慣。編程的規(guī)范與風格是指程序員在編程時應遵循的一套形式與規(guī)則,主要是讓程序員和其他人方便容易地讀懂程序,理解程序功能及作用。
在相當長一段時間,許多人認為,程序只是用來給機器執(zhí)行的,只要程序邏輯正確,能被機器理解和執(zhí)行就足夠了。但隨著軟件規(guī)模日趨龐大和程序復雜性的增加,人們逐漸發(fā)現(xiàn),在軟件生命周期過程中,許多程序都需要被重新閱讀,特別是被編寫該程序以外的其他開發(fā)人員閱讀。這在軟件測試階段和維護階段表現(xiàn)得尤為明顯。當閱讀程序成為軟件開發(fā)和維護過程中的一項重要工作的時候,可讀性差的程序將花費開發(fā)人員更多的時間和精力,而成為耗費軟件系統(tǒng)開發(fā)成本的重要因素之一。
具有良好風格的程序,不僅能讓人們容易讀懂,方便人們修改程序錯誤,而且對程序運行的效率影響不大。而程序設計的風格不能是隨意的,為了讓不同的程序員理解、交流程序,減少因不協(xié)調而引起的問題,應將程序設計的風格統(tǒng)一化。直截了當?shù)倪壿嫳磉_式、通用的語言使用方式、相應的注釋說明等是必不可少的。雖然不同的程序員有不同的風格,但讓程序風格盡量保持統(tǒng)一和規(guī)范,是編程的重要目標之一。因此在建立和使用編碼規(guī)則時應遵循以下幾條原則:
(1)遵循開發(fā)流程,在設計的指導下進行代碼編寫。
(2)代碼的編寫以實現(xiàn)設計的功能和性能為目標,要求正確完成設計要求的功能,達到設計的性能。
(3)程序具有良好的程序結構,要提高程序的封裝性,降低程序的耦合程度。
(4)程序可讀性強,易于理解。
(5)方便調試和測試,可測試性好。
(6)易于使用和維護,具有良好的修改性、擴充性。
(7)可重用性強,移植性好。
(8)占用資源少,以低代價完成任務。
(9)在不降低程序的可讀性的情況下,盡量提高代碼的執(zhí)行效率。程序設計的風格一般包含四個方面:源程序文檔化、數(shù)據(jù)說明、表達式及語句結構、輸入/輸出。
11.2.1源程序文檔化
軟件是程序和文檔的集合。如果認為程序也是一種文檔,那么軟件項目中的文檔是項目開展的唯一憑據(jù)和線索。源程序的文檔化是這樣一種工作:它為源程序的編寫定義了一組相關的規(guī)范,從而確保和提高源程序的可理解性與可維護性。源程序文檔化的內容包括標識符的命名、注釋的安排及程序的視覺組織等。
1.標識符
程序中對常量、變量、數(shù)組、函數(shù)等的命名都是標識符。如定義變量object為一個項目,表示次數(shù)用times,總量用total,定義一維數(shù)組用a[3]表示。標識符應用與它本身含義相當或一致的英文、符號表示,使其能夠見其文知其意。標識符的定義不能太長也不適宜太短,以便于記憶和理解為宜。而且兩個標識符是不應用同一名字命名的,以免引起不必要的錯誤和混淆。
各種編程語言和編程環(huán)境對于標識符的命名和使用都有一定的具體要求,可以參照相應的規(guī)范實例進行學習。
例如,在VC++?里,一般遵循以下一些命名準則:
(1)使用能描述常量、變量或函數(shù)的意義或用途的詞命名。
(2)所有的常量名都用大寫字母的字符串表示,不同的詞之間用下劃線“_”分開。
(3)函數(shù)名中每個詞的第一個字母應大寫,函數(shù)名一般不使用下劃線來分隔詞。
(4)變量命名應遵循匈牙利表示法,變量名以表示變量類型的小寫前綴開頭,其余詞的第一個字母應大寫。
部分常用的數(shù)據(jù)類型對應的前綴如表11.1所示。表11.1匈牙利表示法常用前綴遵循以上規(guī)則,可以寫出以下一些變量命名的示例:
pszName:表示一個字符數(shù)組類型的指針,是一個局部變量。
m_pObject:表示某一個類中的一個成員變量,該變量是一個指向Object的指針變量。
g_blsValid:表示一個布爾(BOOL)類型的全局變量,標識某操作是否有效。
類的命名必須以C開頭,而且緊接著C的第一個字母要大寫。如可以用CStudent表示學生類,用CDlgLogin表示登錄對話框。
Java語言的命名習慣和C++?有些相似,但也有一些區(qū)別。Java常量名和C++?語言一樣,都使用大寫的字符串,如AAABBBCCC。Java包中的字母一律用小寫,如aaabbbccc。類名、接口名應該使用名詞,其中每個單詞的首字母都要大寫,形式如AaaBbbCcc。而它的變量名和類的方法名的命名要求相同,其中第一個單詞小寫,后面每個單詞的首字母大寫,如aaaBbbCcc。
2.注釋
程序中的注釋是程序員與程序讀者之間通信的必不可少的手段。由程序員開發(fā)的程序,在交給維護人員維護的過程中,如果沒有程序的注釋說明,維護人員是很難理解程序的。所以要求在開發(fā)程序時給程序作相應的文檔說明,這些說明是用人的自然語言來描述的。有了程序的注釋,就能給日后程序的修改提供很大幫助。在一些正規(guī)的程序中,注釋行占到整個源程序的1/3~1/2。注釋不影響程序的執(zhí)行。注釋一般分為序言性注釋和功能性注釋。
序言性注釋通常放在每個程序模塊的開始,簡單描述這部分模塊的程序標題、功能和目的說明、數(shù)據(jù)描述、主要算法特征,還有接口說明、模塊位置、開發(fā)簡史等。對理解程序起著引導作用。其中,數(shù)據(jù)描述主要是描述程序中重要的變量及其用途、約束或限制條件;接口說明主要是說明該模塊的調用形式、參數(shù)描述和子程序清單等接口信息;模塊位置標明該模塊在哪一個文件中或隸屬于哪一個軟件包;開發(fā)簡歷包括模塊設計者、復審者、復審日期、修改日期等。
一個模塊的序言性注釋可以是以下形式:
模塊名:該模塊的名稱,相當于模塊的標識符。
功能及目的:模塊主要實現(xiàn)的功能及目的。算法:關于該模塊主要的和關鍵的算法過程的描述。
變量名:關于模塊所使用的各種參數(shù)和變量的說明。
調用者:調用該模塊的其他模塊。
隸屬于:模塊程序代碼所在的源程序文件或包等文件及路徑信息。
作者:程序的編寫者;日期:程序編寫的日期。
審核:程序的審核者;日期:程序審核的日期。
修改:程序的修改者;日期:程序修改的日期。
下面是一個C語言程序函數(shù)前的序言性注釋的例子。通過這些注釋,函數(shù)的功能和調用方法一目了然。類的描述后面才是作者、版本等信息。其中see后面的信息可以作為此類的參考。事實上,Short類是從Number類繼承而來的。since后面一般加版本信息,表示從哪一個版本開始,本程序就已經存在。
功能性注釋嵌入到源程序當中,用以說明其后的語句或程序段的功能,即做的是什么工作。如果程序不是太難理解,一般無需解釋怎么做,因為程序本身就是最好的說明。
例如:
//distance等于speed乘以time
distance=speed*time;
顯然,這樣的注釋對于程序的理解毫無意義,它本身只是程序語句的重復。書寫功能性注釋需注意以下幾點:
(1)用于描述一段程序,而不是每一行語句。
(2)注釋與程序分開,適當使用縮進和空行等方法,使程序和注釋容易區(qū)別。
(3)注釋說明要準確,修改程序也應該修改注釋。
另外,應該避免在一行代碼或表達式中間插入注釋,否則將會使程序的可讀性變差。清晰、準確的標識符命名,合理的代碼組織結構,也會提高程序的自注釋性,從而減少不必要的注釋。從前面的例子可知,應該防止不必要的重復注釋信息,在代碼的功能、意圖層次上解釋代碼的目的、功能和采用的方法,提供代碼以外的東西,以幫助讀者理解代碼。有良好的標識符定義和恰當?shù)淖⑨屨f明就能得到比較好的源程序內部的文檔。有關設計的說明也可作為注釋,嵌入源程序體內,以提高程序的可讀性。
值得一提的是,在Java語言里,由注釋符號“/**”和“*/”括起來的部分稱為文檔注釋,文檔注釋可以用Java提供的javadoc編譯命令方便地轉化為HTML文檔。許多軟件開發(fā)工具和環(huán)境都為程序的文檔化提供了必要的支持。
3.標準的書寫格式
程序的編寫除了要使用規(guī)范的標識符和注釋說明外,還應該注意程序的書寫格式。編寫源程序時遵循統(tǒng)一的、標準的格式,有助于改善程序的可讀性。
一個程序如果寫得密密麻麻,層次不分,顯然讓人難以讀懂。恰當使用縮進和空行,可以使源程序代碼結構更加清晰、美觀。不同的程序段使用空行隔開,可以使冗長的程序代碼更加清晰易讀。而程序的縮進則避免了所有的代碼行都從某一列開始,層次不分。按照程序本身的邏輯關系,對源程序代碼進行必要的組織和編排,使它整體上錯落有序,層次分明,從感觀上來說也更加易于閱讀和理解。
例如,if_else語句可以寫成以下形式:常用的結構編碼規(guī)則一般包括下述幾點:
(1)每一行只寫一條語句。
(2)如果一條語句需要多行,則所有的后續(xù)行往里縮進。
(3)使用分層縮進的寫法顯示嵌套結構層次。
(4)適當使用空格或圓括號作隔離符。
(5)注釋段與程序段以及不同的程序段之間插入空行。
縮進格式有時會導致程序語句延續(xù)到下一行,從而使得程序代碼以至程序邏輯更難讀懂,因而要對程序的嵌套層數(shù)進行必要的限制。而代碼行的長度太長也可能影響閱讀,通常需要進行必要的換行。換行一般應選擇在較高級別處斷開,在一個逗號或一個操作符前斷開。清晰的縮進格式可以增加讀者理解程序的信心。另一方面,不適當?shù)?、前后不一致的縮進格式會給程序的閱讀者造成很大的混亂。但還有一種可能的結果就是,良好的代碼結構使讀者想當然地認為程序編制得不錯,程序邏輯也一定沒有問題。
許多程序編碼工具都對程序代碼的格式規(guī)范提供了良好的支持。例如,不正確的和不適當?shù)目s進所帶來的問題,可以很容易地用自動程序格式化編排程序解決。11.2.2數(shù)據(jù)說明
數(shù)據(jù)說明是程序編碼中必不可少的一部分。雖然數(shù)據(jù)結構的組織及其復雜性在設計階段已經確定了,但對數(shù)據(jù)的說明卻是在編程階段進行的。為了使數(shù)據(jù)說明更容易理解和維護,在編寫程序時,應該注意數(shù)據(jù)說明的風格。
數(shù)據(jù)說明主要應注意以下一些方面:
(1)數(shù)據(jù)說明的次序。數(shù)據(jù)說明的次序應規(guī)范化。從原則上說,數(shù)據(jù)說明的次序可以是任意的,并不影響程序的編譯執(zhí)行。但規(guī)范化的數(shù)據(jù)說明無疑能使程序的閱讀和理解更加容易。應該固定數(shù)據(jù)說明的先后次序,使數(shù)據(jù)的屬性更易于查找,從而有利于程序的測試、調試和維護。例如,可以按常量說明、簡單變量類型說明、數(shù)組說明、公共數(shù)據(jù)塊說明、文件說明的順序進行數(shù)據(jù)說明。在類型說明中,還可進一步要求按整型、實型、字符型、邏輯型的順序進行說明。當一個語句說明多個變量名時,應將這些變量按字母的順序進行排列。例如,如下語句:
intsize,length,width,cost,price,amount;
可以改寫成:
intamount,cost,length,price,size,width;
直觀來說,上述方法顯然可以幫助開發(fā)人員迅速而準確地定位數(shù)據(jù)說明在程序中的位置,有助于提高程序代碼閱讀的效率。
(2)復雜數(shù)據(jù)結構說明。對于一個復雜的數(shù)據(jù)結構,在程序實現(xiàn)這個數(shù)據(jù)結構時應該有相應的注釋說明其特點,使開發(fā)人員能清晰地了解其結構特征。對于用戶自定義的數(shù)據(jù)類型,更應該在注釋中作必要的補充說明。
11.2.3語句結構
軟件的邏輯結構在軟件設計階段已經確定了,但單個程序語句的構造則是編碼階段的任務。程序表達式和語句的構造應力求簡單、直接,不能因為片面追求效率而使語句復雜化。程序員應該以清晰明了的形式寫好程序表達式和語句。一般情況下,一行內只寫一條語句或一條表達式,適當采用移行格式,使程序的邏輯和功能更加明確,增強程序的可讀性。使用基本的控制結構編寫程序,包括順序結構、條件選擇結構和循環(huán)結構。注意goto語句的使用,避免不必要的轉移和相互交叉糾纏,因為這樣只能使程序更加復雜難懂,出錯率高。盡量采用簡單的語句,避免太多的循環(huán)嵌套和條件嵌套,可以用邏輯表達式來
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 隱私防護的影像存儲方案-洞察分析
- 細胞免疫調控策略-洞察分析
- 虛擬現(xiàn)實在創(chuàng)傷后應激障礙治療-洞察分析
- 娃娃玩具行業(yè)人才培養(yǎng)與引進研究-洞察分析
- 天文學與環(huán)境保護-洞察分析
- 衛(wèi)生用品行業(yè)規(guī)范-洞察分析
- 醫(yī)療器械營銷倫理探討-洞察分析
- 消費者權益保護研究-洞察分析
- 2024年棗莊礦務局滕南醫(yī)院高層次衛(wèi)技人才招聘筆試歷年參考題庫頻考點附帶答案
- 2024年核工業(yè)部四一九職工醫(yī)院高層次衛(wèi)技人才招聘筆試歷年參考題庫頻考點附帶答案
- 倉庫班長年終總結
- 組織協(xié)調方案及措施
- 2024-2029年中國IP授權行業(yè)市場現(xiàn)狀分析及競爭格局與投資發(fā)展研究報告
- 北京市海淀區(qū)2023-2024學年四年級上學期期末英語試題
- 2024年湖北省漢江國有資本投資集團有限公司招聘筆試參考題庫含答案解析
- 廣州市九區(qū)聯(lián)考2023-2024學年高一上學期期末教學質量監(jiān)測數(shù)學試卷(原卷版)
- 西方國家的量刑建議制度及其比較
- 游戲方案模板
- 幼兒園大班數(shù)學上學期期末考試-試題測試
- 汽車產品定義 培訓課件
- NICU患兒常規(guī)監(jiān)測和護理要點
評論
0/150
提交評論