《C++程序设计》教案_第1页
《C++程序设计》教案_第2页
《C++程序设计》教案_第3页
《C++程序设计》教案_第4页
已阅读5页,还剩116页未读 继续免费阅读

下载本文档

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

文档简介

《C++程序设计》教案说明:本教案在编写过程中参考了教学大纲中所列的参考文献,在此特向这些文献的作者表示感谢。在教案的撰写过程中,得到了信息エ程学院领导和教师的支持与帮助,在此也向他们表示感谢。第一章C++语言概述本章要点:1、C++源程序的结构和开发过程2、C++语言对C语言在非面向对象方面的增强C++语言的起源及特点从C至リC++C语言最初是美国贝尔实验室的戴尼斯・M・利奇(Dennis.M.Ritchie)在B语言的基础上开发出来的,并于1972年在PDPT1计算机上实现了最初的C语言。C最初用作UNIX操作系统的描述语言,但由于它运算符和数据结构丰富,程序执行效率高,语言简单灵活,可直接访问计算机的物理地址,有大量的库代码和较多的开发环境,具有良好的可读性和可移植性,支持结构化程序设计,所以很快广为流行,成为应用最广泛的程序设计语言之一。然而,C语言仍存在ー些局限:.C语言的类型检查机制相对较弱,使得程序中的一些错误不能在编译阶段由编译器检查出来。.C语言本身几乎没有支持代码重用的语言结构。.C语言不适合开发大型程序,当规模达到一定程度时,程序员就很难控制程序的复杂性。.C语言不支持面向对象的程序设计。为了克服C语言的上述局限,1980年美国贝尔实验室的对C语言进行了扩充并命名为C++〇1.2C++的特点C++的特点主要表现在两方面:ー是全面兼容C;二是支持面向对象的方法。.C++完全包含C,是ー个更好的C。保持了C的简洁、高效和直接访问计算机的物理地址等优点,并对C的类型系统进行了改革和扩充,比C更可靠。.它与C完全兼容,使得许多C代码不经修改就可为C++使用,用C编写的众多库函数和实用软件可以直接用在C++中。.用C++编写的程序可读性更好,代码结构更合理,可直接在程序中映射问题空间的结构。.生成的代码的质量高,软件的可重用性、可扩充性、可维护性和可靠性等方面有更大提高,使得大中型程序的开发变得更容易。.支持面向对象的机制,可方便地构造出模拟现实问题的实体和操作。C++源程序的结构C++程序的一般格式

通过ド面的实例简单说明C++程序的一般格式。例1.1计算两个整数的和。//sum.cpp//sum.cpp#include<iostream.h>intadd(inta,intb)intmain()〃C++的预编译命令,其中的iostream.h是C++〃定义的ー个头文件,设置C++风格的!Z0环境〃函数原型的声明〃主函数intx,y,sum; 〃定义三个整型变量cout«,,Entertwonumber:"《endl;〃提示用户输入两个数cin»x; 〃从键盘输入变量x的值cin»y; 〃从键盘输入变量y的值sum=add(x,y); 〃调用函数add计算x+y的值并将其/赋给sumcout«”Thesumis:,,«sum«,,\n,>;〃输出sum的值return0〃定义add〃定义add函数,函数值为整型〃定义ー个整型变量〃计算两个数的和〃将C的值返回,通过add带回调用处intadd(inta,intb)(intc;c=a+b;returnc;C++程序的结构特点通过以上例子可以看出,C++程序的结构有以下特点:.C++程序通常由包括main。在内的ー组函数组成,函数是构成C++程序的基本单位。其中名为main的函数称为主函数,可放在程序的前部、中部和后部,不论放在程序的什么部位,它总是第一个被执行的函数。因此,ー个可运行的C++程序必须有主函数。其他函数都是被调用函数,它们可以是系统提供的库函数,也可以是用户自己编写的函数。用户自己编写的函数在使用前应给予“声明”。可以说,C++是函数式的语言,程序的全部操作都是由函数完成的。.C++的函数有函数的说明部分和函数体两部分组成。⑴函数说明部分包括函数名、函数类型、函数参数(形式参数)及其类型。如例1.1中add()函数的说明部分为:intadd(int a, int b)ttttt t函数类型函数名形参类型形式参数形参类型形式参数函数类型是函数返回值的类型,如int、float等。无返回值的函数是void类型。main。函数是由操作系统调用的函数,其返冋值是void型或int型。当其返回值为int型时,可使用return语句从main。中返回一个值。例1.1中的返回值为零,意味着main()已被成功执行。函数参数可有可无,但函数后面的圆括号不能省略。⑵函数体函数说明部分下面用花括号括起来的部分,它一般包括如下内容:变量定义:如例1.1main。中的intx,y,sum等。执行部分:由若干语句组成,每条语句以分号结束。如例1.1add函数中的‘'c=a+b;”等。在某些情况下,函数可以没有变量定义部分,甚至即可没有变量定义也可没有执行部分,此时,称该函数为空函数,它不执行任何操作,但合法。如:exem()().C++中的每条语句和变量定义必须以分号结束,即使是程序中的最后一条语句,也必须以分号结束,分号是C++的组成部分之一。正因为如此,可用任何格式书写C++程序,一行内可以写多条语句,一条语句也可分写在多行上。应注意的问题:⑴C源程序的扩展名是.c,而C++源程序的扩展名是.cpp。(2)常用的C++版本如TurboC++,BorlandC++都带有C和C++两种编译器,当源程序的扩展名是.c时,启动C编译器,当源程序的扩展名是.cpp时,启动C++编译器。C++程序的开发过程.程序开发工具编制计算机程序使用的工具称为应用程序开发工具,也称为开发环境。ー个完整的程序开发工具至少应具备如下功能:⑴源文件编辑功能接受键盘输入,显示输入内容,允许用户对输入内容进行修改、编辑。⑵程序编译功能必须有一个能把用户使用的高级语言程序变成机器语言程序的编译程序(也称为编译器或转换程序),该程序在编译的过程中具有发现程序语法错误的能力,该能力是评价编译程序的ー个重要指标。⑶程序文件的连接功能计算机程序由多个文件组成,它们可能是程序开发人员自己开发的,也可能是系统提供的,只有把它们按照程序的要求连接起来才能最终成为可执行文件。因此,开发工具必须具有程序文件的连接功能。(4)程序运行调试功能应用程序中可能出现错误,开发工具必须具有程序的运行调试功能,并能及时反映调试信息,以便尽快修正错误。⑸程序文件管理功能计算机程序由多个文件组成,开发工具应具有使用方便的浏览、创建、删除、改名等管理功能。.C++程序的开发过程⑴选择开发工具C++开发工具很多,如TurboC++、BorlandC++.VisualC++6.0等。这里选用较为广泛的VisualC++6.0(以下简称VC6.0)。(2)用VC6.0建立Workspace进入VC6.0后,选择File菜单的New命令,在New对话框中选择Projects选项卡,在该卡上选择Win32ConsoleApplication(控制台程序)工程选项,在Projectname框中添入工程名称,最后按0K按钮。在以后的话框中选用默认设置,直到建立了工作空间为止。⑶建立并编辑程序使用File菜单的New命令,在New对话框中选择File选项卡,在该卡上选择SourceFile选项,在File框中添入文件名称,最后按0K按钮。此时,建立了ー个扩展名为.cpp的空文件,可在此空文件上书写和编辑C++源文件。(4)编译源文件用工具栏中的编辑按钮编辑源文件。⑸连接用工具栏中的连接按钮连接文件。(6)运行用工具栏中的运行按钮运行文件。C++语言对C语言在非面向对象方面的增强C++不但继承了传统C语言的精华,增加了面向对象的特征,还在非面向对象方面对C语言进行了增强。3.1注释行传统C语言提供的是块注释方式,其格式如下:/*explanationsentence*/C++中,除保留了C中的块注释方式外,又增加了更为方便的单行注释方式,其形式如下://explanationsentence灵活的局部变量说明传统C语言中,局部变量说明必须放在可执行代码的前面,数据说明语句和可执行语句的混合将引发编译错误。而C++中,允许在程序代码的任何地方对局部变量进行说明,所说明变量的作用域是从该变量说明的地方开始到该变量所在的最小分程序的末尾。如for(inti=5;i<=10;i++)在C语言中是非法的,而在C++中是合法的。cin和cout在程序中,常常要把数据从ー个对象传递到另ー个对象中,C++将这种传递称为输入/输出(I/O)流。C++中没有专门的输入/输出语句,为了实现1/O流,C++系统预定义了流类来支持I/O流的操作,cin和cout就是流类预定义的两个对象,使用它们可以完成标准输入和输出。l.cin是标准输入流,在程序中cin代表标准输入设备键盘。使用cin并结合运算符〉〉可以处理从键盘上进行的标准输入,其使用格式如下:cin〉〉存放输入数据的变量名;2.cout是标准输出流,在程序中cout代表标准输出设备屏幕。使用cout并结合运算符<<可以处理标准输出即屏幕显示,其使用格式如下:cout<<待输出的变量名或表达式;.运算符<<和〉〉运算符<<和>〉在C++中仍然保持C中“左移”和“右移”的功能,但当用于输入/输出时,通过重载扩充了他们的功能。重载后的运算符〉〉表示将从键盘上读取的数据传送给右面指定的变量,如:cin»x;此时,从键盘输入的数值会自动转换为变量X的类型并存入X内。但应注意,变量X必须是基本数据类型,而不能是void类型。运算符〉〉允许连续输入ー连串数据,例如:cin»x»y»z;此时,它按书写顺序从键盘上提取所要求的数据并存入相应的变量中。应注意的是,连续输入的多个数据两两之间要用空白符(空格、会车或Tab键)隔开。重载后的运算符<<表示将右面指定的变量的值显示在屏幕上。例如:cout«a;仍然要求变量a必须是基本数据类型,而不能是void类型。运算符<<允许连续输出ー连串数据,也可以输出表达式的值。例如:cout«x+y«a«c;.说明⑴使用cin或cout进行!/O流的操作时,在程序中必须包含头文件iostream.h,否则,编译会产生错误。C++中仍可使用C中stdio函数库中的!/O函数,但只有使用cin〉〉和cout<<才能体现出C++的输入/输出风格。和stdio函数库中的!/O函数一样,cin〉〉和cout<<也可用指定格式精心进行输入/输出。C中常用‘\n’来实现换行,C++仍可使用它。同时,C++又增加了一个换行控制符endl,其作用与,Wー样。如下面的两条语句是等价的:cout<<,,x+y=,,«x+y«,\n,;cout<<,,x+y=,,<<x+y«endl;例1.2使用cin或cout进行I/O操作的例。#include<iostream.h>voidmain()(intage;charname[20];cout<<“你好,请输入你的姓名和年龄:"«endl;cin»name»age;cout<<“你的姓名和年龄是:"<<name<<" "«age«endl;return0;J结构、联合和枚举名作为类型名C++中,结构名、联合名、枚举名都可直接作为类型名,再定义变量时,不用再在结构名、联合名、枚举名前面冠以struct、union、enum。例如,定义结构和枚举如下:structstring{char*ptr;intlength;};enumbool{FALSE,TRUE};当定义变量时,C中必须写成:structstringstr;enumbooldone;而在C++中,结构名string、枚举名bool都被直接作为类型名用,可以直接声明为:stringstr;booldone;无名联合无名联合是C++提供的ー种特殊联合,用来说明一组无标记名的、共享统ー内存地址的数据项。如:union(inti;floatf;);他声明了变量i和f具有相同的存储地址。无名联合通过使用其中数据项名直接存取,如可直接使用上面无名联合的变量i和f:i=20;f=15.0;强制类型转换C中如果要把整型数据转换成浮点型数据,必须用ド面的格式:inti=10;floatf=(float)i;C++保留了这种强制类型转换方式,还提供了另一种方法,即把类型名作为函数名使用,这样就使类型的转换变成了函数的调用,不但方便,而且增强了可读性。使用这种方法,上面的语句就可改写为:inti=10;floatf=float(i);const修饰符C++除可用C中习惯使用的#define来定义常量外,还可使用const修饰符将ー个标识符定以为常量,使该标识符的值在程序运行过程中不能以任何形式对其进行修改。例如:constinti=10;这时,标识符i被const声明为常量,它有类型,有地址,可用指针指向它,但不能修改它。const可以和指针ー起使用,有三种情况:⑴修饰指针所指向的变量,将该变量定义为常量。此时,指针变量的值可以改变,而指针所指向的变量的值不能改变。例如语句constchar*str=&c;声明了一个指针变量str,它指向变量c,但由于用const进行了修饰,所以,变量c变成了常量,其值不允许修改。而指针变量str的值可以修改。⑵将指针本身修饰为常指针,指针所指向的变量不受const修饰的影响,仍为变量。此时,指针变量的值不能改变,称为常指针,而指针所指向的变量的值可以改变。例如语句char*conststr=&c;声明了一个指针变量str,它指向变量c,但由于指针变量str用const进行了修饰,所以,变成了常量,其值不允许修改,而变量c的值可以修改。⑶将指针本身修饰为常指针,指针所指向的变量修饰为常量。此时,指针变量的值不能改变,被指针所指向的变量的值也不能改变。例如语句constchar*conststr=&c;声明的指针变量str和指针所指向的变量c都被定义成常量,它们的值都不允许改变。几点说明:⑴如果用const定义的是整型常量,则关键字int可以省略。⑵常量一旦被建立,在程序的任何地方都不能被修改。⑶与#define定义的常量不同,const定义的常量可以有自己的数据类型,从而使C++的编译器可进行更加严格的类型检査,具有良好的编译检测性。const的作用与#define相似,但使用#define可能会带来程序的不安全性,如下面的程序:例1.3使用#define可能会带来程序的不安全性的例#include<iostream.h>main()Iinta=l;#defineT1a+a;#defineT2Tl-Tl;cout«,,T2is:,9«T2«endl;return0;)初看程序,输出的结果是:T2is:0实际的输出结果是:T2is:2究其原因,是编译系统将语句:cout«MT2is:M«T2«endl;解释为:cout«,,T2is:,,«a+a-a+a«endl;如果用const取代上例中的两个#define语句,将不会引起这个错误。请看下例:例1.4使用const会消除#define不安全性的例。#include<iostream.h>main()(inta=l;constTl=a+a;constT2=T1-T1;cout«5,T2is:,,«T2«endl;return0;}⑸函数参数也可用const说明为常量,以保证实参在函数内部不被修改。ANSIC标准也采用了const,但两者是有区别的,如下面的程序段在C++中是合法的,而在ANSIC中是不合法的:constintsize=10;intch[sizel;另外,在ANSIC中const定义的常量是全局常量,而C++中const定义的常量要根据定义的位置来决定是局部的还是全局的。函数原型C语言建议程序的编制者为程序中的每个函数建立原型,而C++则要求必须为每个函数建立原型,说明函数的返回值类型、函数名称、参数类型及个数。主要目的是在编译时检查调用函数是否与预先说明的原型一致,以维护程序的正确性。函数原型的一般格式为:返回类型函数名(参数表);参数表包括所用的参数和他们的类型,参数之间用逗号分开。例1.5函数原型声明的例。#include<iostream.h>voidprint(char*s);voidmain()(print(4thello,lanzhou!M);)voidprint(char*s){cout«s;}使用函数原型时应注意以下问题:⑴函数原型是一条语句,必须以分号结束。⑵函数原型的参数表中可以不包括参数的名字而只包括它们的类型,如语句longaree(int,char);是合法的。但函数定义中函数说明部分的参数必须给出名字,并且不能以分号结尾。⑶在程序中,函数原型要求出现在函数调用之前,但当ー个函数的定义在前而调用在后时,可以不单独给出它的原型,此时的函数定义的说明部分就起到了函数原型的作用。(4)主函数不必说明原型,它被认为是一个自动说明原型的函数,且不存在被调用的问题。⑸C++的参数说明必须放在函数名后的括号内,不能放在函数说明部分与函数体之间,如下面的程序在编译时将会出错:#include<iostream.h>voidprint(int,char);voidmain(){print("hello,china『);}voidprint(ch)charch; 〃错误的参数说明方式{cout«ch«endl;}(6)原型中没有说明返回类型的函数(包括主函数main),C++默认它的返回类型为int,因此,下面的圆形说明在C++中是等价的:cat(int,char); 〃默认返回整型数intcat(int,char): 〃指明返回整型数⑺如果ー个函数没有返回值,则必须在函数原型中注明返回类型为VOido当主函数没有返回值时,可以在main。前注明void,这样主函数中就不必有“return0”之类的返回语句了。(8)如果原型中没有注明参数,C++假定给函数的参数表为空(void),,下面的原型说明在C++中是完全一样的:f()i 〃表示该函数不带任何参数f(void); 〃表示该函数不带任何参数但在C中,上述两个原型说明是不同的:f(); 〃表示该函数的参数没有给出,它可能有多个参数f(void); 〃表示该函数不带任何参数内联函数C++提供了内联函数,在程序中调用内联函数时,编译器就用该函数的函数体中的代码替代函数调用表达式,这样,不但减少了函数调用时保留现场所用的开销,而且提高了程序的运行效率,同时消除了使用宏定义#define带来的不安全性(产生这个问题的原因是,C中宏定义#define的代码是被直接展开的,而C++的内联函数的代码是被替代的)。要声明一个函数为内联函数,只要在函数说明的前面冠以关键字''inline”就行了。下面的程序中就定义了一个内联函数:#include<iostream.h>inlinefloatcircle(floatr) 〃定义内联函数{return3.1416*r*r;}voidmain(){cout«"areaofcircle:"«circle(3.0)«endl;}使用内联函数应注意如下问题:⑴内联函数在调用前必须进行完整的定义,否则便ー起将无法纸都应给用什么代码替代而出现错误。内联函数通常都出现在主函数之前。⑵当内联函数较长且调用较频繁时,将加大程序的长度。因此,通常将较短的函数定义为内联函数,而将较长的函数作为一般函数处理。带有缺省参数的函数C++在允许在说明函数原型或函数定义时,为ー个或多个参数指定缺省值,以后调用该函数时,若省略其中的某个参数,系统会自动以缺省值作为该参数的值。如ー函数的原型说明如下:intfunc(intx=5,floaty=2.3);则x与y的缺省值分别为5和2.3,下面的调用都是正确的:ftinc(); 〃使用缺省值iunc(10); 〃x使用实参值10,y使用缺省值2.3func(3,4.5); 〃x和y分别使用实参值3,4.5使用带有缺省参数的函数应注意如下问题:⑴当调用带有缺省参数的函数时,编译器按从左到右的顺序将实参传递给形参,因此,所有取缺省值的参数都必须出现在不取缺省值的参数的右边。也就是说,一旦开始定义取缺省值的参数,就不能再定义非缺省的参数,因此,下面的说明是错误的:intfunc(intx,floaty=2.3,chark);⑵在函数调用时,若某个参数省略,则其后的参数都应省略而取缺省值,不允许某个参数省略后,再给其后的参数指定参数值。如下面的调用是错误的:func(10,,'a');1.3.1I函数的重载在传统的C语言中,不允许函数同名,但在C++中,只要函数参数的类型不同,或参数的个数不同,或二者兼而有之,则两个或两个以上的函数可以使用相同的函数名。当两个或两个以上的函数使用同一个函数名时,称为函数重载,被重载的函数称为重载函数。卜.面是函数重载的例。例:1.6函数重载的例子。#include<iostream.h>intmul(inta,intb){returna*b;}intmul(inta,intb,intc)returna*b*c;}voidmain()(intx=2,y=3,z=4;cout«x«,*,«y«,=,«mul(x,y)«endl;cout«x«,*,«y«,*,«z«,=,«mul(x,y,z)«endl;)程序的运行结果是:2*3=62*3*4=24这里强调的是:⑴重载函数必须在参数个数或参数类型上有所不同,不然的话,编译程序将无法确定调用哪个重载版本,即便是返回类型不同也不能区分。⑵一般而言,重载函数应执行相同的功能,例如,abc()函数返回一个数的绝对值,要重载成让他返回一个数的平方根是不可取的。作用域运算符::为了能对当前作用域之外的同名变量进行访问,C++提供了作用域运算符::〇通常情况下,如果有两个同名变量,ー个是全局的,ー个是局部的,则局部变量在其作用域内有较高的优先权。若要在局部变量的作用域内访问同名的全局变量,就必须在该全局变量前加上作用域运算符::。请看下面的例子。例1.7使用运算符::的例。#include<iostream.h>inti;main()(inti=2;::i=10;cout«,,localvariablei=',«i«endl;cout«,,globlvariableiゴvv::ivvendl;)该程序运行结果如下:localvariablei=2;globlvariablei=10;引用引用是C++的新概念,它提供了一种能自动间接引用的指针。也就是说,比不使用间接引用运算符・,就可以得到ー个引用值。引用可为变量(目标)起别名,主要用作函数的参数和函数的返回值。1.引用的定义引用的定义形式为:〈类型标识符〉&引用名=目标名其中,引用名是为引用型变量起的名字,必须遵守变量命名的规则。目标名可以是变量名,也可以是以后将要介绍的对象名。引用名前面的数据类型就是它所要引用的冃标的数据类型。这里特别要指出的是,引用一旦建立,就以对应目标的内存单元地址作为自己的地址,并且不能再改变。当目标变化时,引用也随着变化,反之亦然。例1.8引用的例子。#inciude<iostream.h>voidmain()(inti;int&j=i;i=10;cout<<"i=''<<i<<" jゴ<<j«endl;j=80;cout«''iゴj=''<<j«endl;cout«,,addressofi:,,«&i«endl;cout«''addressofj:,,«&j«endl;}该程序运行结果如下:i=10 j=10i=80 j=80addressofi:oxfff4addressofj:oxfff4由运行结果可以看出,1和上同步更新,并且使用同一个地址。此例的地址为oxfff4(注意:此地址视实际运行而有所不同)。使用引用要注意如下事项:⑴定义引用时,必须立即对它进行初始化,不能定义完成后再赋值。下面的定义是错误的:intI;int&j; 〃错误j=I;⑵为引用提供的初始值可以是ー个变量或对象,也可以是ー个引用。例如:inti=2;int&j=i;int&k=j;⑶引用不可重新赋值,也不可使其作为另一个变量的别名。例如:inti,k;int&j=i;j=&ki 〃错误(4)不能建立引用数组,不能建立指向引用的指针,也不能建立引用的引用,因此,下面的定义都是错误的:int&a[3];int&*ptr;int&&i;⑸当使用&运算符取ー个引用的地址时,其值为所引用的变量的地址。例如:inta=5;int&b=a;int*p=&b;则p中保存的是变量a的地址。2.引用参数引用的ー个主要用途是将引用作为函数的参数,这样,语法更简单,书写也更清楚。为此,先看ー个个例子。例1.9采用按地址传递参数的例。#include<iostream.h>voidswap(int*m,int*n)(inttemp;temp=*m;*m=*n;*n=temp;)main()(inta=l,b=2;coutvv''aゴvvavv"b=,,«b«endl;swap(&a,&b);coutvv''aゴvvavv"b=,,«b«endl;returno;}该程序运行结果如下:a=l b=2a=2 b=l如果将引用作为函数的参数,则程序的书写会变得清晰简单。例!.7采用引用传递参数的例。#include<iostream.h>voidswap(int&m,int&n)(inttemp;temp=m;m=n;n=temp;main()inta=l,b=2;coutvv"aゴvvavv" b=,,«b«endl;swap(a,b);cout<ぐ’aゴvvavv" b=M«b«endl;returno;}C++主张用引用传递取代地址传递。3.引用返回值引用的另ー个用途是将函数说明为返回一个引用,这样,该函数将能用在赋值运算符的左边而对它进行赋值,一般情况下,函数是不能用在赋值运算符的左边的。例1.10将函数说明为返回一个引用的例。#include<iostream.h>intch={1,2,345};int&index(int); 〃声明返回引用的函数voidmain()(index(2)=7: 〃将ch[2]重新赋值cout«index(2)«endl;}int&index(int){returnch[2];}该程序运行结果如下:7应该注意的是,再定义返回引用的函数时,不要返回对该函数内的局部变量的引用。因为局部变量的生存周期局限于函数内部,当函数返回时,它已经消失了,将返回一个无用的引用。如下面的函数返回就是ー个无效的引用:int&func()(intx;// returnx;} 动态内存分配与运算符new和delete.动态内存分配和静态内存分配静态内存分配是指在编译阶段就分配好存贮单元空间,在程序运行过程中,这些空间的大小是不可更改的,也无须对这些空间进行管理,编译时已将管理这些空间的代码加入到目标程序中,在作用域结束后,自动将空间归还系统。动态内存分配是指在程序语句中通过内存分配函数或内存分配运算符取得的存储空间,这样得到的空间的大小,编译器是不知道的,完全由动态运行中的程序的当时情况决定,这些空间在使用完毕后,必须由程序语句显示地将其归还系统。.运算符newnew运算符用于动态分配ー块内存空间,其使用形式为:指针变量=newく数据类型〉其中:数据类型可以是标准数据类型,也可以是结构体类型、共用体类型、类类型等。new运算符返回一个指向所分配的存贮空间的第一个单元的指针,当没有足够的内存空间被分配时,将返回空指针O(NULL)。new能自动返冋正确的指针类型,不必对返回指针进行类型转换。new分配的内存空间是连续的,可通过指针的移动访问所分配空间中的每个单元。new可以自动计算所要分配空间的大小,不必使用sizeof()来计算所需的字节数。例1.11用new动态分配内存。#include<iostream.h>main()iint*p;p=newint;if(!p){cout<<"allocationfailure«endl;return1;}*p=10;cout«*p;deletep;return0;Inew还可以为数组动态分配内存空间,这时要在类型名后面追上数组大小,例如:int*ch=newint[10];要为多维数组分配空间,必须提供所有维的大小,其中第一,维的界值可以是任何合法的表达式。如:inti=3;int*ch=newint[i][4]⑵;new还可以将分配的对象初始化,但不能对动态分配给数组的存贮区进行初始化。如下面的语句是正确的:p=newint(lOO);.运算符deletedelete运算符用于释放由new运算符分配的内存空间。由于内存空间有限,如果只取不还,系统就会很快因内存用完而崩溃。所以,使用delete运算符释放由new运算符分配的内存空间是程序员必须做的ー项工作。凡是由new运算符分配的内存空间,一定要在使用完后用delete释放。delete运算符使用的形式为:delete指针;或delete。指针:其中的第二种形式用于释放为数组动态分配的内存空间。delete运算符后所跟的指针是由new运算符分配空间是返回的指针,也可以是空指针(NULL)。例如:int*p=newint;deletep;char*ch=newchar[10];delete[]ch;使用delete运算符应注意如下问题:⑴由new运算符分配的内存空间,只许使用一次delete,不允许对同一块空间进行多次释放,否则会产生严重错误。⑵delete运算符只能释放由new运算符分配的动态内存空间,程序中的变量、数组等的存贮空间,不得用delete运算符去释放。第二章面向对象程序设计概述本章要点:.面向对象程序设计的基本思想;.对象、类、消息、抽象性、封装性、继承性、多态性的基本概念。面向对象的思想2.1.1结构化程序设计结构化程序设计是为了解决早期计算机程序的难于阅读、理解和调试,难于维护和扩充,以及开发周期长、不易控制程序的质量等问题而提出来的,它的产生和发展奠定了软件工程的基础。结构化程序设计的基本思想是:自顶向下,逐步求精,将整个程序结构划分成若干个功能相对独立的模块,模块之间的联系尽可能简单;每个模块用顺序、选择、循环三种基本结构来实现:每个模块只有一个入口和一个出口。结构化程序设计有很多优点:各模块可以分别编程,使程序易于阅读、理解、调试和修改;方便新功能模块的扩充:功能独立的模块可以组成子程序库,有利于实现软件复用等。所以,结构化程序设计方法出现以后,很快被人们接受并得到广泛应用。结构化程序设计方法以解决问题的过程作为出发点,其方法是面向过程的。它把程序定义为“数据结构+算法”,程序中数据与处理这些数据的算法(过程)是分离的。这样,对不同的数据结构作相同的处理,或对相同的数据结构作不同的处理,都要使用不同的模块,从而降低了程序的可维护性和可复用性。同时,由于这种分离,导致了数据可能被多个模块使用和修改,难于保证数据的安全性和一致性。因此,对于小型程序和中等复杂程度的程序来说,它是ー种较为有效的技术,但对于复杂的、大规模的软件的开发来说,它就不尽如人意了。通过上面的分析可以看出:结构化程序设计的核心思想是功能的分解,思想的特点是将数据结构与过程分离,着重点在过程。用这种方法开发的软件可维护性和可复用性差。2.1.2面向对象程序设计面向对象程序设计是在结构化程序设计的基础上发展起来的,它吸取了结构化程序设计中最为精华的部分,有人称它是“被结构化了的结构化程序设计”。在面向对象程序设计中,对象是构成软件系统的基本单元,并从相同类型的对象中抽象出ー种新型的数据类型ー类,对象只是类的实例。类的成员中不仅包含有描述类对象属性的数据,还包含有对这些数据进行处理的程序代码(这些程序代码被称为对象的行为或操作)。将对象的属性和行为放在ー起作为ー个整体的方法称为封装,它将对象的大部分行为的实现隐蔽起来,仅通过ー个可控的接口与外界交互。面向对象程序设计提供了类的继承性,可通过对ー个被称为基类的类增添不同的特性来派生出多种被称为派生类的特殊类,从而使得类与类之间建立了层次结构关系,为软件复用提供了有效的途径。面向对象程序设计支持多态性。多态性与继承性相结合,使不同结构的对象可以以各自不同的方式响应同一个消息。软件系统中,对象与对象之间存在着一定的联系,这种联系通过消息的传递来实现。在面向对象程序设计中,消息表现为•・个对象对另ー个对象的行为的调用e通过上面的分析可以看出:面向对象程序设计的核心思想是数据的分解,着重点放在被操作的数据上而不是实现操作的过程上。它把数据及其操作作为ー个整体对待,数据本身不能被外部过程直接存取。思想的特点是程序一般由类的定义和类的使用两部分组成,主程序中定义各个对象并规定它们之间传递消息的规律,程序中的一切操作都通过向对象发送消息来实现,对象接收到消息后,调用有关对象的行为来完成相应的操作。用这种方法开发的软件可维护性和可复用性高。支持面向对象的程序设计语言很多,C++就是ー种被广泛使用的、全面支持面向对象程序设计的程序设计语言。面向对象程序设计的基本概念对象和类一、对象和类.对象和类的概念⑴现实世界中的对象和类①现实世界中的对象是我们认识世界的基本单元,世界就是由这些基本单元一对象组成的。如一个人、ー辆车、一次购物、一次演出等等。对象及可以很简单,也可很复杂,复杂的对象可由若干个简单对象组成。对象是现实世界中的实体,具有以下特性:每个对象都有一个用于与其他对象相区别的名字。具有某些特征,称它为属性或状态。有一组操作,每一个操作决定对象的一种行为即对象能干什么。对象的状态只能被自身的行为所改变。对象之间以消息传递的方式相互通信。②现实世界中的类是对ー组具有共同属性和行为的对象的抽象。如人这类是由老人、小孩、男人、女人等个别的人构成,具体的某个人是人这个类的一个实例。类和对象是抽象和具体的关系。⑵面向对象中的对象和类①面向对象中的对象:是由描述其属性的数据和定义在数据上的ー组操作组成的实体,是数据单元和过程单元的集合体。如学生李东是ー个对象,他由描述他的特征的数据和他能提供的ー组操作来表征:对象名:李东属性:年龄:20,性别:男,身高:173厘米,体重:71公斤,特长:篮球运动,专业:计算机科学和技术操作:回答有关自己的提问,计算机软件开发、维护、组网这里的属性说明了李东这个对象的特征,操作说明了李东能做什么。②面向对象中的类:是ー组对象的抽象,这组对象有相同的属性结构和操作行为,并对这些属性结构和操作行为加以描述和说明。类是创建对象的样板,它没有具体的值和具体的操作,只有以它为样板创建的对象才有具体的值和操作。类用类名来相互区别。③对象和类的关系:ー个对象是类的ー个实例,有了类才能创建对象。党给类中的属性和行为赋予实际的值以后,就得到了类的ー个对象。例如人这个类:类名:人属性:年龄,性别,身高,体重,特长,专业操作:回答提问,对外服务当把类名赋予实际的值李东,类的属性和操作赋予李东的属性和操作的实际值以后,就用人这个类创建了一个对象李东。④特别要指出的是,在面向对象程序设计中,类只出现在源程序代码中,不会出现在正在内存运行的程序中,换句话说,类只是在编译时存在,为对象的创建提供样板。对象作为类的实例出现在内存运行的程序中,占有内存空间,是运行时存在的实体。所以类实际上是ー个新的数据类型,要使用它时,要在源程序中说明,而说明部分的代码是不在内存中运行的。在内存中运行的是类的对象,对象在内存中分派空间并完成计算任务,对象通过类来定义。所以,必须严格区分说明和定义两个概念。在C++中,把描述类的属性的数据称为数据成员,把描述行为的操作称为成员函数。.对象的状态⑴对象能够独立存在于现实世界中对象的原因,是每个对象都有各自的特征,这些特征就是对象的状态。如ー个人的姓名、性别、年龄、身高、体重都是他的状态。人的这些状态对人这个类来说,是都具有的特征,因而是静态的。但人的状态又是可变化的,比如年龄会随时间的推移而增大,体重会在不同的时期有轻有重,因而状态的值又是动态的。对象的状态用属性的值来表征,是所有静态属性和这些属性的动态值的总和。⑵面向对象程序设计中对象的状态可以是初等的数据类型,如整型、实型、字符型等,也可以是用户自定义的数据类型,如结构性、枚举型等,还可以是对象,如人的状态除姓名等外,可能有家庭成员,而家庭成员是ー个对象。.类的确定和划分⑴确定和划分类的重要性面向对象技术是江系统分解成若干对象,对象之间的相互作用构成了整个系统。类是创建对象的样板,在整体上代表ー组对象,设计类而不是对象可以避免重复编码的工作,累秩序编码ー次,就可以创建所有的对象。所以,当解决实际问题时,需要正确地进行分类。这是软件开发的第一步工作,划分的结果直接影响软件的质量。⑵确定和划分类的一般原则类的确定和划分没有统ー的方法,基本依赖设计人员的经验、技巧和对实际问题的理解与把握。ー个基本的原则是:寻求系统中各事务的共性,将具有共性的哪些事务划分成一个类。同一系统,达到的目标不同,确定和划分的类也不相同。例如,•个学校系统,目标是教学管理,划分的类可能是教师、学生、教材、课程、教室等。目标是后勤管理,划分的类了能是宿舍、食堂、后勤工作人员、教室等。确定和划分ー个事物是ー个类的步骤是,先判断该事物是否有一个以上的实例对象,有则可能是ー个类。再判断该事物的对象是否有绝对的不同点,没有就可确定它是ー个类。由于问题的复杂性,不能指望一次就能正确地确定和划分类,需要不断地对实际问题进行分析和整理,反复修改才能得出正确的结果。另外,不能简单地将面向过程中的一个模块直接变成类,类不是模块函数的集合。设计类是应有明确的标准,设计的类应该是容易理解和使用的。2.2.2消息.对象的交互现实世界中的对象之间存在着各种各样的联系,正是这种联系和相互作用,才构成了世界中的不同系统。同样,面向对象程序设计中的对象之间也存在着联系,称之为对象的交互,提供对象交互的机制成为消息传递。.方法属于ー个类的对象具有相同的行为,当某个行为作用于对象时,称该对象执行了一个方法,这个方法定义了该对象要执行的ー系列计算步骤,所以方法是对象操作过程的算法。.消息一个对象向另ー个对象发出的请求称为消息,它是ー个对象要求另ー个对象执行某个操作的规格说明,通过消息传递才能完成对象之间的相互请求和协作。例如,学生对象请求教师对象辅导,学生对象向教师对象发出消息,教师接收到这个请求或消息后,オ决定做什么辅导并执行辅导。通常把发送消息的对象称为消息的发送者或请求者,而把接收消息的对象称为消息的接受者或目标对象。接受者只有在接收到消息时,才能被激活・,之后才能根据消息的要求调用某个方法完成相应的操作。所以,消息传递的实质是方法的调用。消息具有如下性质:⑴同一对象可以接受不同形式的多个消息并作出不同的响应。⑵相同形式的消息可以传递给不同的对象,作出的响应可以是不同的。⑶消息的发送可以不考虑具体的接受者,对象可以响应,也可以不响应。对象间传递的消息一般由三部分组成,即接收对象名、调用的操作名和一个或多个参数。ー个对象所能接受的消息及其所带的参数,就构成了该对象的外部接口。消息分为公有消息和私有消息两类,公有消息是由其他对象发送来的消息,私有消息是自己向自己发送的消息。公有消息和私有消息的区分与消息调用的要执行方法有关,如果被调用的方法在对象类中使用public说明的,则为公有消息,如果使用private说明的,则为私有消息,私有消息只能发送调用属于自己的方法。由此可见,类提供了完整地解决特定问题的能力,它描述了数据结构(对象属性)、算法(方法)和外部接口(消息)。对象通过外部接口接受它能识别的消息,按照自己的方式来解释这个消息并调用某个方法来执行对数据的处理,从而完成对特定问题的解决。抽象性人们对世界的各种事物总是分成不同的类来管理的,而抽象是人类对事物进行分类的最基本的方法和手段。面向对象程序设计中的抽象是对ー类对象进行分析和认识,经过概括,抽出ー类对象的公共性质,并加以描述的过程。对ー个事物的抽象一般包括两个方面:数据抽象和行为抽象。数据抽象是对对象的属性和状态的描述,使对象之间互区别的特征量的描述。行为抽象是对数据需要进行的处理的描述,它描述了一类对象的共同行为特征,使一类对象具有共同的功能,因此,又称行为抽象为代码抽象。例如,要设计绘制圆的图形的程序,通过分析可知,圆是这个问题中的唯一事务。对于具体的圆,有的大些,有的小些,圆的位置也不尽相同,但可用三个数据即圆心的横、纵坐标和圆的半径就可以描述圆的位置和大小,这就是对圆这个事物的数据抽象。由于抽象后没有具体的数据,它不能是ー个具体的圆,只能代表ー类事务ー圆类。要能画出圆,该程序还应有设置圆形位置、半径大小、绘制圆形的功能,这就是对圆这个事物的行为抽象。由上面的例子看出,类的数据成员的实质就是解决问题所需要的数据,它是数据抽象的结果;而成员函数的实质是完成对类中的这些数据进行加丄处理的代码,它是类的行为,用行为抽象来描述。因此,抽象性是面向对象的核心。封装性所谓封装,就是把一个事物包装起来,使外界不了解它的内部的具体情况。在面向对象的程序设计中,封装就是把相关的数据和代码结合成一个有机的整体,形成数据和操作代码的封装体,对外只提供ー个可以控制的接口,内部大部分的实现细节对外隐蔽,达到对数据访问权的合理控制。封装使程序中个部分之间的相互联系达到最小,提高了程序的安全性,简化了程序代码的编写工作,是面向对象程序设计的重要原则。面向对象程序设计的封装机制是通过对象来实现的。对象中的成员不仅包含了数据,也包含了对这些数据进行处理的操作代码。对象中的成员可以根据需要定义为公有的或私有的,私有成员在对象中被隐蔽起来,对象以外的访问被拒绝,公有成员提供了对象与外界的接口,外界只能通过这个接口与对象发生联系。可见,对象有效地实现了封装的两个目标:对数据和行为的结合和信息隐蔽。抽象和封装是互补的。•个好的抽象有利于封装,封装的实体则帮助维护抽象的完整性。但抽象先于封装。继承性.基本概念⑴继承的概念在面向对象程序设计中,继承表达的是对像类之间的关系,这种关系使得一类对象可以继承另ー类对象的属性(数据)和行为(操作),从而,提供了通过现有的类创建新类的方法,也提高了软件复用的程度。⑵继承关系的特征类之间如果有了继承关系,它们之间就有如下特征:①类间具有共享特征,包括数据和代码的共享。②类间具有差别或新增部分,包括非共享的数据和代码。③类间具有层次关系。⑶基类、派生类和类的层次设有两个类A和B,若类B继承类A,则类B是由类A派生出来的,类B的对象就具有了类A的一切特征,包括数据和操作,此时称类A为基类(也称父类或超类),称类B为派生类(也称子类)。若类B由类A派生而来,而类C又由类B派生而来,则这三个类就形成了层次结构关系。此时,称类A是类B的直接基类,是类C的间接基类。类C不但继承了直接基类的所有特征,还继承了他的所有间接基类的特征。类的继承特性,给创建派生类提供了•种方法:创建派生类时,不必重新描述基类的所有特征,只需让他继承基类的特征,然后描述与基类不同的那些特征。也就是说,派生类的特征由继承来的和新添加的两部分组成,继承允许派生类使用基类的数据和操作,还可以拥有自己的数据和操作。继承机制提高了软件复用的程度,避免了公用代码的重复开放,减少了代码和数据的冗余,增强了类之间的一致性,减少了模块间的接口和界面,不仅使软件的质量得到了保证,也大大减轻了开发人员的工作量。.继承的分类继承有两种分类方法,ー种从继承源上分,ー种从继承内容上分。⑴从继承源上分①单继承每个派生类只直接继承一个基类的特征。如Windows操作系统中窗ロ之间的继承关系就是单继承。②多继承每个派生类直接继承了不止ー个基类的特征。如小孩的玩具车这个类,就同时继承了玩具类和车类的特征。⑵从继承源上分①取代继承徒弟继承了师傅的所有技术,在需要师傅的地方有徒弟代替。如讲嬴承了桌子的所有特征,但讲桌仍然是ー张桌子。③受限继承如鸵鸟继承了鸟的一些特征,但不能继承鸟会飞的特征。④特化继承如猎犬具有一般犬的特征,但它比一般的犬具有更多的狩猎特征。.继承与封装的关系对象具有封装性,对象的私有成员是被隐藏的,那么,引入继承机制不就削弱了封装性?继承与封装不就茅盾了吗?回答是否定的。一方面,继承机制并不影响对象的封装性。封装的单位是对象,是将属于某个类的ー个对象封装起来,使其操作和数据成为一个整体。如果该对象所在的类是派生类,这个派生类只要把从基类那里继承来的数据和操作与自己的数据和操作一并封装起来就行了,对象依然是ー个封装好的整体,仍然只能通过消息传递与别的对象交互,不能直接调用。可见,在引入继承机制以后,无论对象是基类的实例还是派生的实例,都是一个被封装的实体,继承并不影响封装性。另一方面,继承和封装都提供了共享代码的手段,增加了代码的复用性。只不过,继承的代码共享是静态的,当派生类对象被激活以后,自动共享其基类中的代码,从而实现基类对象与派生类对象共享一段代码。而封装的代码共享是动态的,当在ー个类中说明了一段代码,属于该类的多个实カ在程序运行时共享这段代码。2.2.6多态性多态性是面向对象程序设计的重要特性之一,是指不同的对象受到相同的消息时产生不同的操作行为,或者说同一个消息可以根据发送消息的对象的不同而采用多种不同的操作行为。例如,当用鼠标单击不同的对象时,各对象就会根据自己的理解作出不同的动作,产生不同的结果,这就是多态性。简单地说,多态性就是一个接口,多种方式。C++语言支持两种多态性,即编译时的多态性和运行时的多态性。编译时的多态性是用函数的重载来实现的,运行时的多态性是用虚函数来实现的。这些内容将在相关章节中介绍。2.3面向对象程序设计的语言/

温馨提示

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

评论

0/150

提交评论