高级程序设计语言_第1页
高级程序设计语言_第2页
高级程序设计语言_第3页
高级程序设计语言_第4页
高级程序设计语言_第5页
已阅读5页,还剩102页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第2章高级程序设计语言2.1高级程序设计语言概述2.2高级程序设计语言实现计算的方式2.3高级程序设计语言的基本特征2.4面向对象程序语言的基本特征2.5网络计算时代的编程语言返回2.1高级程序设计语言概述计算机一问世,人们就设计了操纵计算机的语言—计算机语言。最初的语言是机器语言。机器语言在内存中开辟两个区:数据区存放数据;指令区存放指令。CPU从指令区第一个地址开始逐条取出指令并释义执行,直到所有的指令都被执行完。一般的指令格式如下:表2-1中列出了3种类型的指令。机器能“读懂”上面的指令,就是把累加器中当前数再加46。汇编语言面向机器,使用汇编语言编程需要直接安排存储,规定寄存器、运算器的动作次序,还必须知道计算机对数据约定的表示(定点、浮点、双精度)等。下一页返回2.1高级程序设计语言概述这对大多数人来说,都不是一件简单的事情。此外,虽然汇编语言对操作码、寄存器作了一些抽象,但是汇编语言与计算机紧密相关,不同计算机的指令长度、寻址方式、寄存器数目、指令表示等都是不一样的,这使得汇编程序不仅不可移植而且读起来很费劲。汇编语言的这些不足导致了高级语言的出现。上一页返回2.2高级程序设计语言实现计算的方式把一种语言翻译成另一种语言的程序叫做翻译器(如C++翻成C)。把高级语言程序翻译成机器语言程序有两种方法:编译和解释,相应的翻译工具也分别叫做编译器和解释器。下面分别介绍。2.2.1编译器工作原理一个高级语言程序是编译(程序)器的输入。编译器逐行扫描源程序,首先是识别符号串:关键字、字面量、标识符(变量名、数据名)、运算符、注释行、特殊符号(续行、语句结束、数组等)这6类符号,分别归类等待处理。这个过程就是词法分析(LexicalAnalysis)。第二步是语法分析(SyntaxAnalysis)。下一页返回2.2高级程序设计语言实现计算的方式这时一个语句就作为一串记号(token)流由语法分析器处理。按照语言的文法检查每个语法分析树,判定是否为合乎语法的句子。如果是合法句子就以内部格式把这个语法树保存起来,否则报错。这样直至检查完整个程序。如图2-1所示。第三步是语义分析(SemanticAnalysis)。语义分析器对各句子的语法树做检查:运算符两边类型是否相兼容;该作哪些类型转换(例如实数向整数赋值要取整);是否控制转移到不该去的地方;是否有重名或者使语义含糊的记号等。如果有错转到出错处理,否则生成中间代码。第四步是中间代码生成。上一页下一页返回2.2高级程序设计语言实现计算的方式中间代码是向目标码即机器语言的代码过渡的一种编码,其形式尽可能得和机器的汇编语言相似,以便下一步的代码生成。但中间码不涉及具体机器的操作码和地址码。采用中间码的好处是可以在中间码上作优化。第五步是优化。对中间码程序做局部优化和全局(整个程序)优化,目的是使运行更快,占用空间最小。局部优化是合并冗余操作、简化计算,例如x:=0;可用一条“清零”指令替换。全局优化包括改进循环、减少调用次数和采用快速地址算法等。第六步是代码生成。上一页下一页返回2.2高级程序设计语言实现计算的方式由代码生成器生成目标机器的目标码(或汇编)程序,要作数据分段、选定寄存器等工作,然后生成机器可执行的代码。编译过程的示意图如图2-2所示。高级语言源程序经编译后得到目标码程序,但它还不能立即装入机器执行,因为一般情况下它是不够完整的。例如,如果程序中用到abs(),sin()这些函数,可以直接调用,不需实现求绝对值、求正弦的程序,它们一般是标准化了的,事先已作为目标码存放在机器中。所以,编译后得到的目标模块还需进行连接。连接程序(Linker)找出需要连接的外部模块并到模块库中找出被调用的模块,调入内存并连接到目标模块上,形成可执行程序。上一页下一页返回2.2高级程序设计语言实现计算的方式执行时,把可执行程序加载(Loading)到内存中合适的位置(此时得到的是内存中的绝对地址),就可执行了。其示意图如图2-3所示。2.2.2高级语言程序的解释执行编译型语言由于可进行优化(有的编译器可作多次优化),目标码效率很高,是目前软件实现的主要方式。常见的程序设计语言,如C/C++、Pascal、Ada、FORTRAN等都是编译型语言。用这些语言编写的源程序,都需要进行编译、连接,才能生成可执行程序。这对于大型程序、系统程序、频繁使用的支持程序来说是十分有利的。虽然编译时花费了不少时间但程序的执行效率很高。上一页下一页返回2.2高级程序设计语言实现计算的方式不过,在有些场合,如调试程序或者教学过程中,在编译上花费大量的时间似乎并不必要。因此可以对高级语言源程序采取解释执行的方式。解释执行需要有一个解释器(Interpreter),它将源代码逐句读入。和图2-2示意的一样,先作词法分析,建立内部符号表;再作语法和语义分析,即以中间码建立语法树,并作类型检查(解释执行语言的语义检查一般比较简单,因为它们往往采用无类型或动态类型系统)。完成检查后把每一语句压入执行堆栈,压入后立即解释执行。图2-4所示的堆栈首先弹出栈顶元素“*”,从符号表中得知它是“乘法”操作,翻译为机器的乘法指令,要求有两个操作数。上一页下一页返回2.2高级程序设计语言实现计算的方式接着弹出“id3”,查表知道这是变量,可作为赋值号左端操作数。再往下弹出“inttoreal()”,它不是数值而是函数调用(其功能是把整数转换为实数,其执行代码此前已压入执行堆栈),于是寻找inttoreal函数,并弹出参数“60”,执行完的结果作为原表达式的第二个操作数。接着再弹出“+”,表明这是加法运算,第一个操作数已在加法器中,再弹出“id2”,知道是一个变量,可做第二个操作数。执行加法操作后弹出“:=”,再弹出“id1”作为赋值对象,完成赋值。所有的idi按符号表对应地址码,所有运算符对应操作码,换成机器码后立即执行,接着下一句又开始压入栈。解释执行时只看到一个语句,无法对整个程序进行优化。上一页下一页返回2.2高级程序设计语言实现计算的方式操作系统的命令、BASIC、VB、Prolog、LISP、Java、JavaScript、PostScript都是解释执行的,各种应用软件提供的界面语言(一般都很小)多半是解释执行的。解释器不大,工作空间也不大,能根据程序执行情况决定下一步做什么(人工智能经常是这样的)是它的优点。不过,解释执行难于优化、效率较低,这是该类语言的致命缺点。上一页返回2.3高级程序设计语言的基本特征2.3.1变量、表达式、赋值用高级语言编程也是为了对数据实施计算,即将输入的数据经过表达式的计算得到输出数据。然而参与计算的数据特别是计算结果在编程时是不存在的。人们只能用变量表示它。表达式是常量、变量、函数调用和运算符组成的序列。显然,表达式中的变量被赋予数值才可以计算。赋值号左端的变量在写程序时可以没值数值,即使有数值,计算执行之后也会被赋予新值。赋值和函数调用是程序语言改变变量的值的基本手段。不同的语言所使用的赋值号并不完全相同,比如Pascal语言的赋值号是“:=”,而在C、Java、VB等语言中,赋值号是“=”。下一页返回2.3高级程序设计语言的基本特征程序中的一条语句对应着计算机的一条命令(用一条或多条指令来实现)。一个赋值语句就是一条赋值命令。在有的语言中,表达式不能单独成为语句,如Pascal;有些语言没有语句的概念,只有表达式,如LISP;有些语言既可有表达式又可有语句,比如C语言。在C语言中,i++既是表达式也可以看做是语句,称为表达式语句。2.3.2程序的控制结构程序约定自上向下自左向右地执行,也就是顺序地执行语句(或表达式)。如果只能这样,计算机无异于计算器。计算机之所以能自动计算,就是因为它能通过判断将程序转到应该执行的地方。人们就是通过巧妙地安排控制转移,使计算机实施算法。上一页下一页返回2.3高级程序设计语言的基本特征

最基本的程序控制语句在汇编语言时代就有了Jump指令使执行跳转,对应的高级语言语句是无条件转移语句:goto1,其中1是跳转到的语句的标号(数字或标识符),加上条件判断子句if(E)就是条件转移语句:if(E)goto1,其中E是条件(布尔)表达式,求值结果是“真”“假”值。如果为“真”转移到标号为1的语句,为“假”则按顺序执行下一条语句。有了这两个语句再加上简单语句(赋值、调用、输入/输出),就可以实现程序的任何执行控制。最基本的程序控制有以下3种:1.顺序执行简单语句序列S=S1;S2;…;Sn;上一页下一页返回2.3高级程序设计语言的基本特征2.选择执行如下面的语句。右边的复合语句是按当今结构化程序设计语言表示法表示的,机器内部实现更接近于左边的描述。3.循环执行上一页下一页返回2.3高级程序设计语言的基本特征这3种执行控制的任意组合和重复、嵌套就可以描述任意复杂的程序。

结构化程序的控制结构早期的编程语言是语句级的,用简单语句集合加goto构成复杂的程序控制。然而显式地使用goto语句是极其危险的。这是因为:(1)goto语句相互交织使设计出的程序控制结构成为不可分解的一个整体。上一页下一页返回2.3高级程序设计语言的基本特征(2)显式使用goto语句使得任何写错转移语句标号的小错误都会导致灭顶之灾。(3)即使程序控制逻辑是结构化的,显式使用goto语句,程序依然难于阅读。图2-5(c)所示的流程图看似复杂其实不复杂,细分不外乎图2-6所示的3种控制结构。这3种控制结构中每个矩形框或整个结构都只有一个入口和一个出口的控制流线。每一方框很容易以另一基本结构置换。这样,基本结构的重复嵌套可以构成极其复杂的程序。上一页下一页返回2.3高级程序设计语言的基本特征Boehm和Jacopini证明了它们的表达能力是完备的。它的好处是:(1)天然支持自顶向下逐步求精的开发。当程序不太明朗时用方框,细化时换成结构。(2)程序控制结构清晰不易出错。(3)出了错易于找出错误并修改。(4)易阅读导致易扩充、修改,大程序易于分析。程序控制结构清晰,是它用关键字控制程序块(语句组)。任何控制转移不能进入这些控制块,除非通过入口。块中转出也不能直接转到程序其他处,只能转到出口。在出/入口增加检查语句就使得程序错误真正局部化。上一页下一页返回2.3高级程序设计语言的基本特征程序块级(语句组)控制采用语句括号Keyword…Endkeyword非常清晰,使程序逻辑与表示法结构完全一致。图2-5(b)中的程序是用结构化编程语言,也就是第三代语言(3GL)书写的,它几乎与其下面的流程图一样,表示和逻辑一致,可直接编程。因此,程序语言结构化以后,编程对流程图的依赖就很少了。此后,Nassi—Schneldermann提出了结构化流程图(主要取消流线及箭头),但因没有直接用类似结构化编程语言的伪代码方便而没有流行起来。

结构化编程语言的其他控制结构结构化程序只需3种基本结构重复和嵌套。上一页下一页返回2.3高级程序设计语言的基本特征1.条件分支1)无假块条件分支和嵌套if语句有下列结构:if(E)thenSTendif如图2-7(a)所示。if(E1)thenSlelseifE2thenS2…elseSmendif如图2-7(b)所示。无假块条件语句是正规条件语句的简化,很常用。嵌套语句在否定部分用关键字elseif,有的语言用elsif。只有当所有条件均为“假”时才执行else块。显然,逐个检查m个条件效率很低,有时似无必要。上一页下一页返回2.3高级程序设计语言的基本特征2)case语句也叫分情形语句。根据条件变量Z的值单独执行S1,S2,…,Sn,执行完Si自动跳到endcase(C语言例外,它要加上break才跳。否则执行Si+1

到Sn)。形式如图2-8所示。2.循环结构除了while(E)doSenddo结构之外,还有do-until和for结构。1)do-until语句形式是doSuntil(E)enddo,其流程图如图2-9(a)。它是先执行再判断,若E为“真”不再循环。正好和先判断再执行的do-while语句是相反的。将它改成dowhile结构十分容易。条件取反,先执行一次S块,如图2-9(b)所示。上一页下一页返回2.3高级程序设计语言的基本特征2)for-do语句以控制变量增减值或枚举集合值计数的循环,其流程图如图2-10所示。For-do是do-while的另一种变体结构,其书写格式又有多种变体。for(iinA)doSenddoA是一个集合,循环次数是A中元素的个数,每枚举1个元素循环1次。3)do-while-do语句其形式是doS1while(E)doS2enddo,流程图如图2-11所示。把与条件无关的部分或影响E值的计算的部分作无限循环。E为“真”才作S2,否则执行enddo后面的语句。上一页下一页返回2.3高级程序设计语言的基本特征3.顺序控制通常把一切影响正常顺序执行的,如调用/返回、前跳、延迟、异常、控制语句都归结为顺序控制。常见的有以下语句。goto多数语言作为历史遗留保留,不提倡使用,Java中取消了该语句。breakC/C++中用于跳出块到endcase(switch)。continue仅用于循环,立即结束本次循环,作下次循环。call-return调用过程,返回后执行下一句。exit立即跳到末端出口。abort(STOP)强行停止本程序。上一页下一页返回2.3高级程序设计语言的基本特征delayXX延迟XX时间后继续执行。raise-exception引发异常,处理异常。执行了raise后跳到exception指明的异常处理段执行,处理后不再返回。在VB、C++中是try-catch-finally语句,把可能出现异常的代码放入try块(它包含catch、finally两种块),通过throw引发,catch捕捉后处理,finally为可选的善后处理。2.3.3数据类型计算机中计算对象(不管是常量、变量)都是有类型的,不能把一个实数(如32.7)和逻辑“真”值(True)相加。上一页下一页返回2.3高级程序设计语言的基本特征指出数据类型的一个目的就是要避免这类错误的发生。各语言转换函数(inttoreal或realtoint)不尽相同,有的是把待转换的类型名作为转换函数名,但要点是在本语言允许的兼容范围内。不兼容的类型,如整数和布尔型一般不能转换,但C语言例外。

常用的基本类型最常用最基本的数据类型就是纯量类型,一般来说,几乎所有类型的程序设计语言都提供了下面几种基本数据类型:int/integer'整型对应为数学中整数real/float/double'实型(浮点类型)对应为数学中实数logical/boolean'布尔型(逻辑型)只有“真”假”值上一页下一页返回2.3高级程序设计语言的基本特征char/character'字符型ASCII码的所有可见字符string'字符串类型enum'枚举类型,用户预定义的一串标识符强类型语言(所谓强类型,就是编译时所有变量类型均确定,类型转换必须显式地给出)决不允许这种灵活性,而无类型语言则无需变量的类型声明,给它什么值它就是什么类型。VB恰是这两种语言的混合。

数组类型变量代表单个数据值叫纯量变量。如果代表多个数据(数组)或多种数据(记录)就叫它结构型数据的变量。上一页下一页返回2.3高级程序设计语言的基本特征数组的特征是所有元素均为同一类型。

记录类型从以上叙述知道,数组中每个值的类型都是相同的。但是,现实中有些事物,它们的属性的数据类型并不是完全相同的,比如说,人的身高、性别、年龄、出生年月等数据,它们的数据类型并不一样。身高是实数、性别只能是字符串,年龄的数据类型是整数,而出生年月则是日期型数据。显然不能直接用数组来记录有关人的信息,于是,引入了记录数据类型:相同或不同类型数据组成的结构被称作记录。记录型数据记录了对象的属性信息,记录的各个组成部分,称为记录域,各个域的数据类型可以不相同。上一页下一页返回2.3高级程序设计语言的基本特征类型定义中列出了属性名和属性的数据类型。记录类型变量的一组值(或一行值)称作元组(tuples),由属性变量的值组成。每个属性变量指明了一个(取值)域,也叫字段。如表2-2所示。有了这个类型就可以声明记录型变量。该变量在运算中只能按域取值,域的表示法是变量后接符号“.”再接域(属性)名。嵌入的数组或记录的元素又可以是记录或者数组,这样嵌套下去可以形成非常复杂的数据结构。所以一般语言有了数组和记录的定义机制就足够了。需要说明的是,在C语言中,记录被称作结构。上一页下一页返回2.3高级程序设计语言的基本特征结构或记录都耗用较多的内存空间,早期语言均设有变体记录。因为发现有一些域不是在程序所有运行期间都要用到,将它占用的空间在程序运行的后期换成另一些域(显然类型不一样),就叫做变体。C语言还专门发展了这种技巧,称它为联合(Union)。既然同一存储域可以有两种类型解释,那么存入整数或字符按哈希码解释。快速查找可省去很多运算。但当今存储空间没有以前紧张,应用层次上用变体记录就很少了。

指针类型指针类型是一种很重要的数据类型,但同时也是一种简单却不大好理解的数据类型。上一页下一页返回2.3高级程序设计语言的基本特征在讲述指针之前,首先来看一个例子(采用C语言来描述):每个变量都有一个名字(标识符),对应为存储单元的地址,存储单元的内容为变量的值。引用变量的值时直接把变量名放到用值的地方(赋值语句的两边)。程序运行时按地址存取内容。如果某个变量的值是内存中的地址,这个变量被称作指针变量。它是指向另一变量的变量。只是“另一变量”没有名字,它的地址直接放到指针变量的存储单元中去了。所以,指针变量可以间接地引用某个值。上一页下一页返回2.3高级程序设计语言的基本特征图2-12中,指针变量p同样可以运算和赋值,但必须是指针类型的运算和赋值。如果变量p的内容不变,它就是常量指针。C语言中指针类型如同数组类型,以类型指明符“*”表示。它所指向的对象是有类型的。指针和引用为操作程序对象提供了方便。当定义和引用简单对象时,用变量就足够了。名字是地址,值是内容。值可以改变,但值所在的存储单元(值的结构)不能变。复杂对象就不方便了。上一页下一页返回2.3高级程序设计语言的基本特征指针为操纵复杂对象带来了极大的方便。指针类似于在数据对象中用goto,简洁、灵活、实用。C语言利用指针发展出的一套编程技巧是系统程序的精髓。但指针使用不当,如悬挂指针,是程序出错的根源之一。特别在当今分布网络背景下,要在不同站点上传递程序,指针就不能使用了。因为各站点地址码是不一样的。在A站点上指针的值到B站点上就无法解释。Java坚决取消指针,对象所要求的递引用则由引用类型保留。2001年出现的C#语言,更是把引用类型推向极至:凡对象类型均为引用类型,常规类型是值类型。它们可以通过装匣(boxing)和脱匣(unboxing)任意转换。上一页下一页返回2.3高级程序设计语言的基本特征2.3.4过程图2-13是一个函数过程。函数过程是参数化(更抽象)的程序。

过程的定义从过程关键字开始到过程结束之间的一段封闭的程序就是过程定义,它由型构(signature)和过程体(Body)组成,以下是两种过程定义的结构:上一页下一页返回2.3高级程序设计语言的基本特征

过程调用函数过程因返回值可以出现在主程序的表达式中,以函数名引用函数值。并列出与形式参数表变元的个数、类型、次序一样的实在参数表。子程序过程的使用是过程调用,它相当于浓缩的一段程序(一个独立的语句)。过程调用是把过程体的代码调回到主程序的环境下执行。形式参数和实在参数变元匹配之后过程运行,和主程序中其他代码运行没什么两样。这样,主程序中声明的变量在过程中自动可用。但反过来不行,请看图2-14所示:上一页下一页返回2.3高级程序设计语言的基本特征以上就是所谓的全程变量和局部变量,局部变量在过程执行完之后所有的数据和过程体都消失了,因此出了过程体再引用过程中的变量当然出错。过程调用这种执行机制,为程序运行、节省内存空间带来了极大的好处。程序中的数据对象,自它声明时起到本程序块结束(见到End)为其有效的作用范围(作用域)。显然,内块嵌入在外块内,外块的变量,内块中是能见到的,这就可能导致这样一个问题:外块的变量与内块同名怎么办?程序设计语言中以“就近声明优先”准则来处理。如图2-14,内块程序中所有出现X的地方均按布尔类型解释,Double型的X虽在其作用域内但被覆盖(Overrided)了,因此不可见,只有通过点表示法才能出现在内块中,如下所示:上一页下一页返回2.3高级程序设计语言的基本特征2.3.5过程的数据传递过程是一段封闭的程序,型构是它与外界通信的接口,它的变量是抽象的,只有通过形、实参数匹配才能具体执行。执行出口是本过程末端(除非中间有显式的return语句)。数据出入有两个途径,一为全程量,一为参数表。上小节已说过全程量,此处讨论参数表。

无参过程过程的型构中没有形参表,调用时也不需要实参变元。过程中用到的数据是所在环境的全程量或自己内部声明的局部变量:上一页下一页返回2.3高级程序设计语言的基本特征上一页下一页返回2.3高级程序设计语言的基本特征其中用到全局对象txtFeet、txtInches、MeterResult和全局函数CDbl、Format。这种风格在可视化语言中比比皆是。

传递变元从主程序向过程传递数据可以有两种方式:传值和引用。请看下例。上一页下一页返回2.3高级程序设计语言的基本特征先执行不包括方括号内两句的程序,结果为上一页下一页返回2.3高级程序设计语言的基本特征若执行加上方括号中两句的程序,结果为所以传值是很安全的,局部程序不会改变全局变量的值。其缺点是占用双倍存储单元,这对大型数组来说是个值得注意的问题。传值的另外一个缺点是带不回值。变元参数传递是过程中非常重要、非常基本的概念,是两种不同的实现过程运算的机制。每种语言都加以区别。缺省是一种,显式标注是另一种。上一页下一页返回2.3高级程序设计语言的基本特征2.3.6变量的生命期和Static变量程序中的变量生命期随其声明所在程序块而异。程序一执行完它的所有数据变量均失去意义,它所在的存储区则可另行分配其他程序装入执行。因此,主程序中变量的生命期比过程中变量生命期要长,内嵌的子过程其变量生命期更短,最长的是文件变量,它放入磁盘,程序没有了它依然存在,所以按“生命期”的长短有:持久变量除非人为销毁全局变量出了程序便失去定义静态局部变量见下文上一页下一页返回2.3高级程序设计语言的基本特征自动变量(局部变量)出了所在块便失去定义循环控制变量出了循环便失去定义常常有一种需要,一个局部变量在它所在的局部程序块消失后依然保留其值,又不希望它为全局变量而被该局部块以外的程序引用。2.3.7输入/输出程序总得把计算的结果告诉使用者,输出一个可识别的结果。非简单计算情况下还得在运行时获得用户的输入。程序的输入/输出分作两大类:一类是程序之间以文件形式进行数据传递;另一类是人—机交互,把人们可识别的形式(字符串、数)按一定格式输入到程序变量中。上一页下一页返回2.3高级程序设计语言的基本特征输出则相反,按用户要求的格式显示或打印。这一般由高级程序设计语言以过程调用(标准过程)的形式实现。过程在高级语言内部通过调用操作系统的系统调用完成。C语言也是把格式合并到输入(scanf)和输出(ptintf)函数中,这组函数在终端上功能很强,一般形式是输入/输出一个串,串中特殊符号“%”指示格式,出现几次“%”串后跟几个待输入/输出的变元。在VB中,可以利用MsgBox函数创建一个消息对话框,向用户反馈程序,输出信息。上一页返回2.4面向对象程序语言的基本特征2.4.1对象概述依据前面第3节提供的主要机制,编制结构化的过程式程序就不会有什么问题。按照解题模型精心设计数据和算法过程,即可写出程序。过程式程序的结构是层层调用如同一棵树。下层程序除自己声明的数据外共享上层和上上层程序声明的数据。图2-15中子程序aa、ee如果都用到主程序声明的数据,它们之间就有关系。一个子程序改动了(如重新赋值)共享数据则另一个必然受影响。这种现象叫数据耦合。过程模块虽然把大程序切小了,但每个程序块独立性并不强。下一页返回2.4面向对象程序语言的基本特征所谓独立指一个模块修改了(甚至删除)对其他程序块没有影响,如果子程序分得更小,一个过程只实现一种功能,过程块数量上去了,独立性就会相对增强一些(有更多模块不共享数据)。现在软件的过程子程序小而多是其特色。尽管如此,有了共享数据,当程序规模进一步增大时查错、调试仍然极其困难。试设想有100个子程序模块,每个模块都单独测试过,合在一起调试时总出错,那只好沿其执行路径去找,如图2-15(b)所示。但是由于程序中有条件判断,可能跳过某些模块,执行路径因输入值不同而不同,模块越多可能的路径越多。测试的困难就越大。上一页下一页返回2.4面向对象程序语言的基本特征“分而治之”的思想使人们想到进一步封装,即把相关的数据与过程装在一起,尽可能让它独立。如图2-16所示,设想一个程序有100个子程序,经过分析,这100个子程序并不是每个子程序都要用到所有的数据,把相互关联的数据和程序(有嵌套调用)分成组。这样,一个大程序分成了5个大模块,只留过程接口等待外面调用。当然,模块间也可以彼此调用,例如图2-17中,Sub22调用Sub89、Sub43调用Sub62等。尽管数据可沿着调用路线来回串,但最后加工结果都落实在各模块声明的数据存储单元内,总结果若在第二、四模块内,下一道打印命令(也是调用),它就把自己那组数打印出来。上一页下一页返回2.4面向对象程序语言的基本特征进一步分析发现这些大模块的数据和操作往往是描述客观世界中的一个对象,例如一个堆栈、一台打印机、一个雇员、一个窗口……拿数据堆栈来说,堆栈体(由数组或队列类型实现)、入栈的数据和栈高指示(变量)就是堆栈的数据,压入(Push)、弹出(Pop)就是它的基本操作,询问是否空(IsEmpty)是否满(IsFull)是它的辅助操作。这样封装的程序块就是一个复杂的计算对象:私有的数据描述了本对象的状态(如数据堆栈的情况);操作表示了本对象的行为(能接受询问IsEmpty、IsFull,会压栈Push,会弹栈Pop);对象接受外界的消息而动作,其结果是改变了对象内部的状态(数据在栈中出入)。请参看图2-18。上一页下一页返回2.4面向对象程序语言的基本特征这样封装之后使用者就不必关心对象内部情况,只按接口规定的形式向它发送消息(如同调用)就可以了。如对象的设计者发现某个操作的算法(过程体)不好,重新改写一个,使用者也不用知道,只要接口形式不变就行。过去只有数据类型及数据结构、过程(算法描述)和嵌套过程,把一个活生生的世界硬拆成过程式程序表达,使用者要知道许多内部细节,设计者调试起来也极不方便。程序对象提供了直接描述客观世界对象的有力手段。数据叫做对象的属性(Attribute),操作则改称方法(Method),即改变属性的方法。上一页下一页返回2.4面向对象程序语言的基本特征对象间相互只有通信,调用方法叫发消息(Message)。消息—方法与过程调用—过程体的定义几乎完全一样,但意义不同。过程式语言在过程调用时主程序等待直至过程返回;消息则不一样,因对象是自主的程序实体,发消息者可等可不等,接受消息的对象可以立即响应可以稍晚些响应,这降低了对象间的引用耦合,为并发程序、事件驱动程序提供了程序实现的技术基础。2.4.2类与对象

消息和方法上一页下一页返回2.4面向对象程序语言的基本特征消息(Message)相当于过程语言的过程调用,可带实在参数;方法(Method)则相当于过程定义,带参数也是形式参数,一定要有方法体(执行语句集)。面向对象中只有消息—方法,没有过程调用—过程体的说法。类对象只接受生成、撤消实例对象的消息,这些方法称为类方法。用到的变量相应地称为类变量。类定义中的其他方法和数据变量叫作实例方法和实例变量。

类与类型类是由简单类型组成的复杂类型,和用户定义的学术上叫抽象数据类型(ADT)的复杂类型有相似之处:上一页下一页返回2.4面向对象程序语言的基本特征(1)类型名封装数据和操作。(2)数据由若干基本类型或已实现的复杂类型定义的变量组成。(3)操作是加工这些数据的子例程和函数。(4)有外部可见性控制public(公有)、private(私有)。不同之处:(1)类定义实例变量参与程序运行,类型仅是对变量的计算形态的描述,不参与运行。类也是程序对象参与程序运行。(2)子类型是类型的真子集,不是操作减少就是数据取值范围缩小,子类是类的例化,它增加数据和操作,使对象更明确。上一页下一页返回2.4面向对象程序语言的基本特征(3)过程式程序的执行顺序,尽管是并发程序,都是设计者事先考虑好了的执行过程。面向对象程序由于对象相对独立可以支持事件驱动程序。面向对象程序天然支持这类应用,如图2-20所示,对象A、B、C都是独立的,连线是表示运行时发消息的路径,不运行时没有。空心箭头表示触发的消息(例如鼠标点击),图示给出两个,谁先谁后都没有关系,增加或减少一个对象或方法,只需对用到它的其他对象稍作修改,不需要更改总控程序。2.4.3类定义面向对象编程,要学会定义类。上一页下一页返回2.4面向对象程序语言的基本特征VB的所谓面向对象编程是不彻底的,它的控件都是对象,但其类定义由系统做,用户只能在它提供的属性和方法的前提下,生成并使用实例对象,用户全无类定义概念。VB.Net回到面向对象语言的大家庭,才提供了类定义机制。本节用C++举例。类定义以类名封装类成员,类成员分数据成员和方法成员。只有指明它们是公有(Public)成员,其他类的对象才可以访问,私有(Private)成员类内成员均可访问。数据和操作全部公有,失去封装和数据隐藏的意义,全部私有只是一个孤立的对象,也失去对象通信模拟客观世界对象的意义。所以,一般是数据成员全部私有,方法成员多半公有,少量私有。上一页下一页返回2.4面向对象程序语言的基本特征私有方法只接受公有方法的消息,间接为类外对象服务。

构造子和析构子类是对象的制造厂,生成的实例对象在运行前必须初始化,这个工作如果在定义数据成员时都加上初始化属性值,生成的对象雷同,就没有必要定义类了。所以每个类都定义一个构造实例的方法叫构造子(Constructor,C++译为构造函数,因为它的操作只有函数),用户设定不同的参数,就可以构造出不同的实例,在2.4.2节例的main()中stkl是可装100个字符的堆栈,stk2为可装20个字符的堆栈。构造子一般与类同名,在声明实例对象时也就等于在给类对象发消息。上一页下一页返回2.4面向对象程序语言的基本特征同名的构造子可以定义多个实例,这样,构造实例的方法多样编程就很方便。方法的名字相同,所带参数不同,即方法体不同,这叫重载(Overloading),即一个名字代表了好几个方法。在编译或运行时根据参数的类型、个数、次序匹配。析构子(Destructor)和构造子相反,当程序不再需要该实例对象时,及时撤销以释放它所占据的空间。析构子的定义是在类名前加“~”号,不带参数,在main()中写以下语句:上一页下一页返回2.4面向对象程序语言的基本特征则撤销stk2对象。

接口类定义方法的型构也称为与方法体的接口,它和方法体的显式分离不仅使得编写程序方便,而且还带来其他好处。面向对象语言如Java、C#,均提供接口类。接口类的定义为:上一页下一页返回2.4面向对象程序语言的基本特征它是没有属性变量和方法体的类,显然它不能运行。此刻向接口类的实例发消息全然无用,必须还得有一个类把它的方法型构一一实现才能运行。上一页下一页返回2.4面向对象程序语言的基本特征2.4.4类继承类的封装保证了程序的模块独立性,这样,调试程序比较方便。但封装也带来问题,相同的数据,相同的操作,每个类封装一套(例如四则运算、两数比较、Hash索引等)那就太繁杂了,继承能解决这个问题。每个类都可以派生许多子类,子类继承父类的属性和方法。子类又可以派生它的子类……老祖宗的属性和方法可以一代一代传到最新派生的(子)类。上一页下一页返回2.4面向对象程序语言的基本特征把最“老”的称为Object,把一般四则运算、两数比较等大家都用得到的属性和方法定义在其中,以后派生类就不用写了,只定义派生类“自己的”属性和方法,这就构成树状的继承体系,如图2-21所示。2.4.5多态性注意到上述类中有许多方法是同名的,但是,由于它们所属类不同,编译器不会弄混。例如Print_List方法:上一页下一页返回2.4面向对象程序语言的基本特征现在,在程序中进行声明并使用定义的对象:上一页下一页返回2.4面向对象程序语言的基本特征此时p->Print_List()就是多态的,有时是父类Employee实例的数据,有时是子类Manager实例数据,因为面向对象允许子类实例就是父类实例。*p所代表的既可以是雇员也可以是经理,这种多态性的好处是不因雇员、经理数量多少而更改程序。请注意在给定的C++程序中若没有虚函数Virtual关键字,这种自动动态切换是无法实现的。上一页下一页返回2.4面向对象程序语言的基本特征由于继承,属性和方法可能重名,这就产生了多态(同一名字执行内容不同)。静态(在编译或连接)时就可以分辨的叫作重载(Overloading),例如多个构造函数是最常见的。运行中根据执行情况才能决定束定(也叫作邦定)到哪个方法体。2.4.6类继承带来的新问题

概括继承继承不仅仅为了重用,少写代码的聚集,继承父类的方法和属性,加入本类自己的属性和方法,越聚越大,派生类越来越有用。上一页下一页返回2.4面向对象程序语言的基本特征如图2-23(b)所示,写这种继承的各个类定义不会有困难,但派生类的实例不可能定义父类实例,“平房”决不是“点”类实例对象,因其违背了模型客观世界对象继承的关系。面向对象假定的继承是概括继承。如图2-23(a)所示,任何派生类的实例都是父类实例。

多继承多继承的体系结构是一个网状模型。C++支持多继承,在定义类时写:上一页下一页返回2.4面向对象程序语言的基本特征Java和C#坚决不用多继承,类库是单继承的树状模型,而实际问题要多继承怎么办?用接口类解决,作如下定义:class类名:[Public]父类名,[Public]接口类名1,[Public]接口类名2,…

可见性规则有了继承关系,以前设定的可见性规则就复杂化了,既然是“血统”关系,以前不对外开放的(私有)成员,对子孙就要开放。所以,类定义中Protected指出该成员对家族外是私有,对内公有。真正私有的还只限于本类方法访问。图2-24给出派生类中成员的可见性。上一页下一页返回2.4面向对象程序语言的基本特征就派生类而言,父类私有的成员(不计继承其他类的)一律隐含是派生类的私有成员。除非父类选择protected,派生类也不能访问这些私有成员。父类公有成员不声明[public]也是私有。当然,详细的规则还要看各语言的参考手册。

嵌套类可见性当一个类的成员不是属性和方法而是类class时,叫做嵌套类。这些子类和其父类不是派生—继承关系而是直接包容关系。嵌套类成员的访问性控制和普通成员的访问性控制的关键字解释是一样的。没有修饰符的嵌套类为包容类私有类,它的实例外部不可访问,加public修饰后的内嵌套和一般普通类的使用没什么差别。上一页下一页返回2.4面向对象程序语言的基本特征由于继承和包容在面向对象语言增加了许多修饰性的关键字,要弄清楚继承、包容、可见性控制并不难。当然,少数关键字是为其他机制增加的,以下是Java的类和类体声明:上一页下一页返回2.4面向对象程序语言的基本特征其中与类和继承有关的关键字public、abstruct、protected、private、static、extends本章均已解释。若用final修饰类,该类不再派生;修饰变量,该变量等同于常量。

类体系的组织由于继承和面向对象化,有了类库编程越来越简单。这些支持编程的类(VB叫做构件和控件),有的是应用程序的一部分,有的是调试工具和翻译工具(Debugger、Compiler、Linker等),有的是工作平台的支持(从最直接的应用到操作系统)。如图2-25(b)所示,系统类、系统工具类、应用基础类、应用类不分彼此,大家都是类对象,直接或间接都是Obiect的子类。上一页下一页返回2.4面向对象程序语言的基本特征如图2-25(a)所示,由于类过于庞杂,面向对象提出名字空间(NameSpace)的概念作类体系结构管理。每字空间可以嵌套,每个名字空间下有若干个类。名字空间实际是子类系统和子系统的别名。因为在分布式环境下如此庞大的类支持不一定在一个站点,也不知道某串子类支持在哪里。有了名字空间系统就可以按名自动索引使用,最新面向对象语言Java、C#均设NameSpace机制,Java中叫做Package(包)。上一页返回2.5网络计算时代的编程语言2.5.1HTML和XML网络计算在网站之间传递的是主页。主页按http协议传递,页面格式是HTML(超文本置标语言)。每个站点上都有浏览器可以识别以约定标签标记过的正文,标签成对形如:<tag>正文</tag>标签层层嵌套,如一本书先章、节、段落后复合语句、简单语句。经过标记之后一段正文信息就成为结构化数据。传到另一站点后,浏览器读出这段正文,就原封不动地转移了,即使是图文并茂的多媒体文档也照传无误。上一页下一页返回2.5网络计算时代的编程语言但HTML约定的60多个标签表达能力有限。它只知道传递的内容是符号串和二进制块。于是,人们发展了可以由用户定义标签的XML(可扩展的置标语言)语言,从而可描述页面的数据内容。页面格式由XSL或CSS子语言描述。XML可描述数据关系比较复杂的数据结构,如图、表、树、索引文件和数据库中定义的数据关系。在数

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论