第六章复合数据类型_第1页
第六章复合数据类型_第2页
第六章复合数据类型_第3页
第六章复合数据类型_第4页
第六章复合数据类型_第5页
免费预览已结束,剩余10页可下载查看

下载本文档

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

文档简介

1、第六章 复合数据类型6.1 变量和赋值的进步讨论一个变量是由四个要素组成的: 一个名字、一个属性、一个关联和一个值。 名字指命名变量 的标识符; 属性指变量可以存放那种类型的值; 关联指存放变量的内存位置; 值指该内存位 置当前时刻存放的数据。应该认识到这里的值是可能改变的, 但任何时候在盒子里总有一个值 (我们将无定义的随机 值也当做一个特殊的值) 。根据变量在赋值运算中的使用方式,将变量的关联部分称为左值,变量的值部分称为右值。 对于表达式而言, 求值结果也存在是否可作为左值使用的问题。 一般情况下, 表达式的求值 结果作为右值使用,但如果一个表达式的求职结果不是void 类型,并且指派了

2、一个变量,则该表达式可作为左值。./合法的赋值运算 /不合法的赋值运算(i<0)?i:j)=1(i+j) =16.2 指针类型变量以两种方式被使用:作为一个关联的名字和作为一个值的名字。 对变量的访问也有两种方式:直接访问和间接访问。在C+中实现对变量的间接访问的方法是:先安排相关变量,专门用于存放变量地址。 要间接访问时, 先从这些变量获得待访问的变量的地址, 然后再按所获得的地址去访问要访问的 变量。指针是存放其他变量地址的变量, 所以从效果上看它们指向这些数据。 指针使得数据不一定 非得与某一特定变量名字相关联,指针可以指向一个没有名字的数据值。6.2.1 指针的声明int age

3、 = 30;/声明一个存放年龄的整数类型变量让C+编译程序知道有一个新的变量,该变量的名字是标识符age,编译程序会为它分配2个字节的存储空间(假如我们使用的机器上 int 用两个字节表示)并将 30放在这些字节中, 并且编译程序知道这些字节中存放的是整数类型数值而不是浮点类型或其他类型数据。不直接访问age的存储空间地址,而是用age这个名字访问器其存储空间。ptr 常用作 pointer 的缩写指针类型是在其他数据类型后加一个类型修饰符“ *”,这个类型被称为指针的基类型。如 int * age_ptr;注意“ *”仅用于修饰类型,而不是变量名字的一部分。 一个指针变量占用的存储空间大小取

4、决于机器的内存寻址方式。指针age_ptr的类型(int*)指明age_ptr仅能指向整数类型的值,而不能指向字符类型、浮点类型或其他类型的值,即age_ptr中存放的地址所指向的存储空间中只可存放整数类型的值。将“*”与类型名写在一起表明 int* 是一种复合类型,但要注意Int * p,q;声明的却是一个整数类型的指针变量P和一个整数类型变量q如果把“ *” 和指针变量写在一起,则可以连续声明几个指针变量。例如: int *p,*q,*k;注意(int *)并不能作为一个类型来使用,例如(int *) ptr;并不是一个声明,编译程序会将它理解为类型转换。6.2.2 指针的引用“&

5、”运算符放在操作数前面,操作数必须是一个变量名,表示取出操作数的存储空间地址; ”*”运算符也放在操作数前面,操作数必须是一个指针变量,表示取出指针所指向存储 空间中保持的值。在一个指针变量前面加上“ *”有两种情况:一是声明一个指针变量,此 时作为类型修饰符;二是访问指针变量所指向的变量的值,此时作为一元运算符。空指针是值为 0x00 的指针变量,许多编译程序提供的函数库中定义了一个空指针名字NULL,其作用相当于 0x00,赋值语句:ptr=NULL; 相当于 ptr=0;int *ptr;声明指着 ptr 时没有初始化它,所以 ptr 中存放的值是不确定的,它随机地指向某一内存区域(这个

6、区域的内容可能很关键) 。如果为初始化 ptr 就使用它:*ptr = 250;那么存放250的两个字节将可能会写入内存中的关键区域。C+语言在编译与运行时都不报告这种错误, 这种错误在程序开发后期才能被发现, 并且这种错误的出现具有随机性, 因而 错误的定位与修改变得十分困难。6.2.3 指针的运算指针变量的算术运算只能做加、减运算。 必须注意指针的算术运算与指针的基类型是密切相关的。例如指针 age_ptr 的当前值为 350606 ,经过如下运算: age_ptr = age_ptr + 1;age_ptr的当前值不是350607,而是350608。因为指针age_ptr的基类型是int

7、,所以指针age_ptr每次加 1就指向下一个整数,所以他存放的地址值是加 2 而不是加 1。6.2.4 按引用调用的参数传递方式引用类型是在其他数据类型后加上一个类型修饰符 “ & ”,该数据类型被称为引用的基类型, 例如int&是基类型为int的引用类型。注意“ &”在C+语言中既可作为类型修饰符,也可 作为一元运算符(取操作数的地址)或二元运算符(两个操作数进行位与运算) 引用类型的变量并不真正创建一个新的对象,而是作为另一个对象的别名。int i =1;/真正创建了一个整数类型的对象并初始化为1int& ir = 1;/引用类型的变量必须初始化,指明ir

8、 是 i 的别名引入 ir 作为 i 的别名后,对 ir 的运算就相当于作用在变量 i 上。ir = 8;/相当于将 8 赋值给 icout<<&ir;/相当于输出 i 的地址将函数的返回值类型C+语言引入引用类型的主要作用是提供按引用调用的参数传递方式。 定义为引用类型时,函数调用表达式可作为左值使用。按值调用 按引用调用 由于按引用调用不需要复制实际参数的一个副本,因而按引用调用的效率要高于按值调用, 特别是当参数时比较大的复合数据类型时。 有时候为了效率而使用按引用调用的参数传递方 式,即使并不需要修改这些实际参数的值。为确保函数无副作用,可以使用保留字const 修

9、饰这个形式参数。6.3 数组类型在数学上, 常用一个向量表示一些相关数据组成的序列。 在程序设计中,用数组来表示,数数组中的每一个元素均属于同一类型,这种类型称为数组的基类型;每个数组中的元素个数一经确定后就保持不变,称为数组的长度; 数组中的每一个元素均能直接访问,用数组下标来标识数组的元素; 数组中的元素还允许是数组类型,从而产生二维数组、多维数组等结构。组是数据项的有序列表,这些数据项称为数组的元素。程序中数组有以下特点:(1)(2)(3)(4)6.3.1维数组的声明一维数组是相对多维数组而言, 指数组中的元素不再是数组类型。 一维数组只需要一个参数 就可以确定数组内的一个数组元素。一维

10、数组的声明方式为:类型 数组名 常量表达式 ;常量表达式可出现常量或符号常量,但不允许有变量,因为C+语言不允许动态确定数组的长度,如:int N;cin>>N;int scoresN; /出错,因为 N 是变量一个数组的所有元素在存储空间中是连续存放的, 两个相邻的数组元素之间没有空隙。 编译 程序将根据数组的长度以及数组的基类型为数组分配相应大小的存储空间。编译程序为数组分配的存储空间地址是不确定。数组的大小可以用 sizeofO运算符取得,如果 sizeofO的操作数是一个数组变量,它将返回整 个数组占用的存储空间字节数。6.3.2 一维数组元素的引用与初始化程序中使用数组时

11、, 通常引用的是数组中的一个个元素, 而不是整个数组变量, 如在屏幕上 输出数组scores中的内容,不能用Cout<<scores;/输出结果不正确(输出的是数组的起始地址)而必须将数组中的元素逐个地输出到屏幕。6.3.3 数组作为函数的参数要想将数组传递给函数,函数形式参数中的数组必须给出数组的基类型以及左右方括号“ ”,这样编译程序才能理解这个参数是一个数组类型的变量,而不是其他数据类型。由 于在数组声明时已确定了这个名字的数组长度, 所以在形式参数中没有必要再次给出数组的 大小。C+语言也允许在方括号中写上数组的长度, 但在方括号中写任何数字或没有数字都 可以正常工作,这些

12、数字仅起一个注释作用。在C+语言中,编译程序对数组进行处理时,自动将数组名转化为指向这个数组首元素的指针(数组首元素的地址) 。所以,在函数调用时,只须给出数组的名字作为实际参数。所有 数组都是按引用被自动传递过去(实际上是它们起始地址的一个副本),因此如果给一个函数传递一个数组作为实际参数, 并且在这个函数中改变了数组元素的值, 那么, 函数调用返 回时这些改变仍然保持着。按值调用的参数传递方式的最大好处是函数调用没有副作用,因为被调用函数的执行结果不影响调用程序中的数据。 但数组作为函数参数时是按引用调用的, 如果不想再函数体中改变 数组元素的值,如何保证函数调用没有副作用呢?可以在函数原

13、型中数组参数前加上const修饰符, 以显式指明调用该函数对数组是没有副作用的, 即数组中的任何元素对不能再改函 数体中改变。6.3.4 一维数据应用举例冒泡排序法:将相邻的两个数据做比较,把较小的数据交换到前面6.3.5 二维数组的声明如果一个数组的基类型是一维数组, 则称这种类型为二维数组。 二维数组需要两个参数方可 确定数组内的一个数组元素。声明二维数组的一般形式为:类型 数组名 常量表达式 常量表达式 ;int scores50,3;/语法错误 “50,3”是逗号表达式,相当于 int scores3;为二维数组分配存储空间可以有以行为主和以列为主两种。以行为主 (以行优先) 是一行一

14、行地存,各行按列次序连续存储,一行存完后再存下一行。以列为主(以列优先)是一列一 列地存,各列按行次序连续存储,一列存完后再存下一列。在 C+ 中,一律采用 ”以行为主 ”的存储形式。6.3.6 二维数组元素的引用与初始化int matrix34 = 1,2,3,4,1,3,5,7,2,4,6,8;int matrix34 = 1,2,3,4,1,3,5,7,2,4,6,8;int matrix34 =1,2,2,3,5;与一维数组相似,在C+语言中,编译程序对二维数组进行处理时,自动将数组名转化为指向这个数组首元素的指针 (数组首元素的地址 )6.3.7 二维数组应用举例符号常量的值是不可修

15、改的,所以使用全局符号常量并无什么副作用。一维数据作为参数时, 可以不给出数组的大小; 但二维数组作为形式参数则必须给出数组的 大小(或只给出第二维的长度)6.3.8 指针与数组指针类型变量可以当做数组使用,数组类型变量也可当做指针使用。C+语言的数组名字只是一个指针而已。虽然数组名字也是一种指针类型,但它是一种常量指针类型,其值是不可改变的。C+语言允许以指针形式访问数组元素正是需要利用指针是变量这一特点来弥补数组名字作为常量 指针的不足,以提高处理数据 (特别是一组连续数据 )的能力和简化对数据的操作方式。6.3.9 指针数组与数组指针指针数组是指基类型为指针类型的一个数组,而数组指针是指

16、基类型为数组类型的一个指 针。如果需要保留许多指针的值,可以使用指针数组。如:int * ptr_array10;的优先级高于 *,所以 ptr_arrary 先于10 结合,组成长度为 10的数组形式, 然后才决定这个 数组中的每一个元素师指针类型 (int *). 。如果写成 int(* array_ptr)10;那么声明的将是一个指针类型的变量array_ptr,它指向一个长度为10的整数类型数组。6.4 字符串字符串实际上是基类型为字符的一个特殊数组, 一个 0 值字节表示串结束。它与普通字符数组的区别在于字符串最后有6.4.1 字符串常量与变量'A'只分配一个字节的存

17、储空间,而为字符”0”。因为括住字符串的字符串”A ”与字符'的区别,编译程序为字符串”A”分配两个字节,其中一个字节存放 A的ASCII编码,第二个字节存放串结束标志 C+语言在处理字符串时, 全靠这个结束标志才知道字符串的终止位置, 双引号并没有存储起来,不能用它们为字符串确定边界。字符串的长度是指字符串中所有字符的总和, 包括其中的空格以及其他转义字符在内, 尽管 转义字符在字符串中占了几个位置, 但只当做一个字符计算长度。 一个字符串常量占用的存 储空间是其长度加 1 个字节,因为最后还要存储一个串结束标志。字符串变量是一个基类型为字符类型的数组变量,同样遵循“先声明、后使用“

18、的原则。字 符串定义的一般形式为:Char 数组名 元素个数 ;在声明字符串常量时,可以字符串常量进行初始化,如:char name30 = ”Zhongshan University ”;这时编译程序会为字符串变量name分配30个字节的存储空间,并将"Zhongshan University ”中 20 个字符的 ASCII 码存储在前 20 个字节中,然后在第 21 个字节中放一个 ”0”表示串结 束,至于第 22 个至第 30 个字节是什么内容是不关心的。 字符串变量占用的存储空间大小与 其中存放的字符串的长度之间没有相等关系,尽管name中存放的字符串长度为 20,实际使用

19、了 21个字节,但它仍然占用着 30个字节存储空间。鉴于上述存储空间组织方式, 在初始化字符串变量时一定要注意字符串长度不要超过其存储 空间大小,如:char name20 =”Zhongshan University”;可能会引起严重问题,因为字符串的结束标志”0”超出了为它分配的存储空间变价,可能破坏了其他数据。C+语言为避免上述字符串越界错误,也帮助程序员提供了一条捷径,即不必声明字符数组的长度,由编译程序根据初始化的字符串常量的长度自动决定。如:char name = “Zhongshan University ”;name 分配 21 个字节,相当于对于这个声明,编译程序会根据字符串

20、常量的长度为char name = “Zhongshan University ”;for 或 while 并且以由于字符串是一个字符类型的数组,所以既可以用数组下标方式访问字符串中的各个字符, 也可用指针方式访问。逐个访问字符串中的字符时,一般使用循环语句 判断字符是否为 '0'作为循环结束条件。6.4.2 字符串数组const int max_subjects = 24; char* subjectsmax_subjects;6.4.3 关于字符串操作的库函数在其他地方不允许name 不允许作为一个 ”与其他类型的数组一样, 只可在声明字符串变量时用赋值运算作初始化, 直接

21、使用赋值运算,如:char name30;name = “Zhongshan University ”;/语法错误因为 name 实际上是一个常量指针,不可用赋值语句改变其值,即 左值 ”。可以每次使用循环语句逐个字符赋值一个字符串,或比较两个字符串的每一个字符是否相等,但这一类常用操作已由C+系统提供,只要使用以下语句即可完成字符串的复制:strcpy(name,”Zhongshan University ”);string 。这些常用函数组织成标准库的形式供程序员重用,该标准库的名字为#include <string.h>'0'(1) unsigned int

22、strlen(const char* str);返回字符串 str 中字符个数,包括其中的空格与转义字符,但不包括结束标记(2) char* strcpy(char* str1,const char* str2);将str2指向的字符串复制到str1指向的位置并返回str1。注意为str1分配的存储空间必须能放下 str2 指向的字符串。以下是初学者常犯的错误:char* str;strcpy(str,”Be careful ”);/ 可能引起严重的问题因为 str 所指向的存储空间地址是不确定的,我们还没有让这个指针指向一块已分配到 的存储空间。char* str;str = “Be car

23、eful. ”;因为字符串常量已经分配了存储空间,赋值后指针char str20; strcpy(str, ”Be careful ”);因为 str 已经静态地分配了 20个字节的空间, 所以可以将字符串常量复制到这一存储空 间。注意为str静态或动态申请的存储空间大小不可小于12个字节,否则会出现越界写入错误。str 指向这一空间。(3)char* strcat(char* str1,const char* str2);将字符串 str2 连接到字符串 str1 后,形成一个新字符串,原先 str1 的结束标记 '0'被取 消。函数返回值为 str1。注意为字符串常量 st

24、r1分配的存储空间一定要足够大,能够容 纳两个字符串连接后的新字符串。(4)(5)int strcmp(const char* str1,const char* str2);比较两个字符串 str1 和 str2 的内容是否相同(按字典排序方法) 。如果 str1 小于 str2 则 返回负数,str1等于str2则返回零,str1大于str2则返回整数。char * strchr(const char* str,int ch);寻找字符串str中第一出现字符ch的位置。如果找到ch,则返回指向该位置的指针,否 则返回空指针。(6)char* strstr(const char* str1,c

25、onst char* str2);寻找字符串 str2 在字符串 str1 中第一次出现的位置,不包括 str2 的结束标记 '0'。如果 找到str2,则返回指向该位置的指针;否则返回空指针。6.4.4 字符串与指针数组应用的例子(主函数带参数)程序员写出源程序之后, 要利用编译程序吧源程序转换为机器语言程序, 再利用连接程序把 编译所得的机器语言程序组织处理成为可装入内存并执行的可执行机器语言程序(或称可执行文件),最后才能执行这个程序。得到了可执行目标程序之后, 在操作系统环境下, 直接输入可执行文件名便可以执行这个程 序,不必每次都从源程序编译、连接后才去执行。主函数带

26、参数stdlib.h把指针s所指向的数字字符串转换为整数int atoi(const char*s);把指针s所指向的数字字符串转换为实数Double atof(const char* s);把指针s所指向的数字字符串转换为长整数long atoll(const char* s);主函数带参数主要有以下两种方式:(1)(2)(3)(int):(double):(long):int main(int argc,char* argv);int main(int argc,char* argv,char* env);其中 argc 是一个整数, 表示传给主函数的命令行参数个数, 其实际值是实际参数个

27、数加 1(把命令本身也当做一个参数) ;argv是一个指针数组,argvO指向命令(包括路径);argv1指向执行程序名后的第一个 参数,argv2为执行程序名后的第二个参数, ,依此类推。env也是一个指针函数,env的每一个元素将指示相关的环境值(作为一般用户实际没 有必要去详细了解它) 。6.5 指向对象的指针对象一经声明就为对象的成员分配踩踩空间, 并调用其构造函数进行初始化, 对象生存期结 束时自动调用其析构函数,并释放对象占用的存储空间。一种较好的解决途径是先声明这些对象, 但并不立即分配存储空间和调用构造函数, 在需要 这些对象时才这样做, 使用完这些对象后立即调用其西沟函数并释

28、放其占用的存储空间, 而 不是留待对象生存期接受才有 C+系统自动回收存储空间。这一途径是使用C+语言指向对象的指针。由于使用对象指针比直接使用对象更加灵活、方便, 所以应尽量使用对象指针代替对象。特别是作为函数参数或返回值时,使用对象指针比使用对像本身具有更清晰的语义。6.5.1 对象指针如果声明的一个指针的基类型是一个类类型, 那么这个指针称为对象指针, 它指向一个对象。 如:CIRCULAR_NUMBERS * angle_ptr;注意这时 C+仅仅为这个指针分配了存放指针值的存储空间,并没有分配存放一个属于CIRCULAR_NUMBERS 类型的对象空间。用运算符“ ->”访问这

29、个对象的公有数据成员或成员函数。如:angle_ptr->increment();相当于:angle.increment();在C+语言一个类的成员函数体中,都隐含提供了一个对象指针,这个对象指针用保留字 this命名,它指向该成员函数正在操作的对象。保留字 this不常用,只是在需要返回当前对 象或指向当前对象的指针时才用到 this.6.5.2 对象的动态创建与撤销C+语言使用new和delete运算符完成对象的动态创建与撤销。运算符 new 的一般形式为 :指针 = new 类型名 (初始化表 );如果其中, 初始化表及其括号是可选内容,类型既可以是基本数据类型,也可以是类类型。

30、是类类型,则初始化表相当于将实际参数传递给该类的构造函数。例如: int* int_ptr;int_ptr = new int; 又如: char* string;string = new char40;char* string = new char40l注意这里使用方括号与静态声明一个数组时使用方括号的区别: 声明数组时方括号内只允许 出现常量表达式,而 new 则允许在表达式在使用变量。分配了存储空间后才能使用 strcpy() 函数,如:strcpy(string, ”Zhongshan University ”); 以上动态分配的 string 与以下静态分配的 string2: ch

31、ar string240;strcpy 函数从另一个字符串复制过来。但 stringstring2 是一个常量指针,它不能指向其他的字符串,例如:均占用 40 个字节的存储空间,都可以使用 是一个指针变量,而 string = string2;是合法的,而/错误string2 = string;new 分配存储空间,如: CIRCULAR_NUMBERS* angle_ptr; angle_ptr = new CIRCULAR_NUMBERS(0,359,250); 在类型名字后用圆括号括住构造函数的实际参数,在new 操作是 angle_ptr 所指向对象的构造函数才被调用,并且完成存储空间

32、的分配。如果我们设计的类没有构造函数,那么 new 后只需要接着类的名字,圆括号与初始化表均不出现。由 new 分配存储空间并不保证每一次都成功。如果new 分配存储空间失败,则返回给指针的值是一个空指针 '0',即一些标准库中定义的名字 NULL 功,继续使用这个指针是很危险的。由经验的程序员在每次 配是否成功,然后再决定下一步的操作,其模式如下:则是不合法的。对于类类型也可以用。如果这时不考虑 new 操作是否成 new 操作后,都会判断内存分CIRCULAR_NUMBERS* angle_ptr;angle_ptr = new CIRCULAR_NUMBERS(0,359

33、,250);if(ngle_ptr)if( angle_ptr = NULL)/内存分配失败后的处理/内存分配成功后的处理else ./ 如果不再需要所分配的存储空间,可以使用 delete 运算符释放它们。如: delete int_ptr;delete string; 第一条语句释放了指针 int_ptr 占用的存储空间, *int_ptr 变得没有意义的了。第二条语句释 放了 string 所指向的 40 个字节, string 将不再存放字符串内容。注意用 delete 释放空间后, 指针的值仍是原来指向的地址,而不是空值 NULL 。不能通过测试指针是否为 NULL 来判 断该指针所

34、指向的空间是否已经释放。 释放内存操作只能做一次, 已经释放过的指针再次释 放时将产生错误。对于指向类类型的指针使用delete操作时,会同时调用该类的析构函数。如:delete angle_ptr;如果使用 new 运算符申请的是一个类类型对象的数组,如:ptr = new STUDENT50;则使用delete运算符释放时应加上方括号对”,以确保调用数组中每一个 STUDENT对象的析构函数,如:delete ptr;当程序中不再需要使用分配来的存储空间时, 一定要记住释放这些空间。 如果这些空间不释 放,那么在整个程序运行过程中,这些内存一直被占用, 无法再分配给其他程序。 如果指向 这

35、一存储空间的指针的值被改变(指向另一存储空间位置) ,或该指针的作用域与生存期结 束,就将无法在释放这些空间。 这些无法再回收的存储空间成为内存垃圾, 内存垃圾的不断 增长将会耗尽所有内存,最终导致系统崩溃。由于当前的C+语言运行环境不支持自动垃圾回收功能,所以一定要谨慎对待内存垃圾问题。如果没有必要就不要让多个指针指向同一个地址。/生命整数类型的指针 /生命整数类型的指针ptr1 ptr2在使用对象指针时还要尽量避免别名, 用别名由潜在的危险,如: int* ptr1;int* ptr2;指向分配到的空间/申请空间并将 ptr1/使 ptr2 指向与 ptr1 相同的地址ptr1 = new

36、 int; ptr2 = ptr1; 当 ptr1 和 ptr2 互为别名后,执行 delete ptr1;会使两个指针都变成无效的。 程序员可能忘记了释放 ptr1 的同时也释放了 ptr2 ,如果继续使 用 ptr2 将导致内存混乱。6.5.3 对象的复制与比较对象的复制与比较是针对对象的数据成员而言。C+语言提供的缺省情况,将对象中的数据成员逐位地复制给另一个对象。这种对象复制是 当对象的数据成员中不出现指针时,不会产生什么问题。当有指针的时候, 也是逐位地将对象的数据成员复制给另一个对象, 但这时只是对象中指针 的值赋值给了另一个对象的同名字的指针, 而所指向的内容并未复制, 结果是两

37、个对象中的 指针均指向同一个字符串, 造成内存垃圾与指针别名的出现。 其后果是当一个对象撤销时释 放了指针所指向的内容,导致另一个对象指针无效。由C+语言缺省提供的对象复制策略成为浅复制,这种对象复制方法很简单,但经常无法满足需要,因为对象中的指针只复制了原来所指向内容的地址,而内容本身没有复制。程序员位解决这一问题而自定义的对象赋值策略称为深复制。只要按深复制策略编写拷贝构造函数与重载赋值运算符”,就可以像使用 C+语言缺省的对象浅复制一样使用自定义的对象深复制。6.6 指向函数的指针6.6.1 函数指针/C+一个函数的入口地址, 指的是执行这个函数时, 首先被执行的第一条指令所存放的存储单

38、元 地址。 C+ 语言允许指针指向一个函数,称为函数指针。这时因为函数在编译时被分配了一 个入口地址, 这个入口地址可以作为函数指针的值。 我们可以通过函数指针来调用一个函数。 通过函数指针调用函数与通过函数名字直接调用函数的参数传递方式是相同的。 声明函数指针时与声明函数一样, 也必须包括类型的说明。 为函数指针赋值时, 整个函数类 型必须严格匹配。函数指针的定义形式为: 函数类型 (* 函数指针名 )(形参表 );/C/C+类型以及返回值类型完全相同。或 函数类型 (* 函数指针名 )(形参表 ); 函数类型相同是指函数形式参数的个数、 void error(char *msg)/ 定义一

39、个错误处理函数 cout<<msg<< ”n”; /将错误信息输出 return;可以使用函数指针调用这些错误处理函数 main()void (* handle)(char*); handle = &error;(* handle)( “Error occurs ”);/声明一个指向错误处理类型函数的指针 /让 handle 指向错误处理程序 error() /通过函数指针调用函数 error()注意由于函数调用运算符 ”()”的优先级高于 ”* ”,所以声明函数指针时不能写成 void* handle(char *)/声明一个返回值为 (void *) 的函数

40、利用函数指针调用函数时也不能写成* handle( “Error occurs. ”)/ 类型错误6.6.2 函数指针作为参数指向函数的指针通常是很有用的, 例如常用的鼠标器驱动的图形用户界面就是利用指向函数 的指针实现各种操作的。 当用函数指针作为参数时, 就可以告诉一个函数怎样完成一个任务, 由一个函数决定在适当时候通过函数指针去毁掉指定的函数。C+ 语言的构造函数是没有返回值的, 因此无法通过检测构造函数的返回结果来判断对象的 构造函数是否成功执行。在C+语言的类中进行异常处理的一种简单、有效方法是使用函数指针。如果希望同一异常处理程序被该类的所有对象共享, 就将函数指针声明为静态的;

41、如果希望每一个对象都有自 己的异常处理程序,就将函数指针声明为普通成员。例如class DEMO_CLASSpublic:/设置用户自己的异常处理程序void set_error_handler(void (* user_handler)(int); private:static void (* error_handler)(int code);类 DEMO_CLASS 要求所有异常处理程序必须有一个整数类型的形式参数且返回值类型为 void, 所有对象实例公用一个异常处理程序。这个异常处理程序可以是创建对象时缺省提供 的,也可以由用户编写并提供。 在异常处理程序中,根据错误代码显示出错信息,

42、 然后简单 地终止程序 (也可以在异常处理程序中设计一些高级的 undo 操作)。简单地终止程序可使用 C+语言的库函数exit(),括号中的参数相当于 main()函数中return的值,这个库函数的原型 定义在 stdlib.h 或 process.h 中6.6.3 主动对象6.7 结构类型、枚举类型与类型别名6.7.1 结构类型结构类型属于复合数据类型。 义出自己所需的数据类型 均同时存在。结构类型 式 public 或 private 时, struct 结构类型名 成员成员用户可以利用已定义的数据类型的数据项和系统规定的规则定 结构类型。 在一个结构类型中, 构成它的各个成员在任一时刻 struct 的作用域 class 非常相似,其区别仅在于没有成员访问控制方 class 缺省为 private,而 struct 缺省为 public。1 说明 ;2 说明 ;n 说明 ;成员;正如 class 的声明一样, 由于通常结构中没有定义操作(尽管/只有数据成员 struct 声明最后的分号 ”;”不可缺少。C+语言允许在结构中定义操作,但这时常用保留字 class来定义),因而结构不是抽象数据类型的一个实现,所以通常不建议使用结构类型。C+语言的函数只能返回一个值,在需要返回多个值时可以通过参数返回,这时参数必须按引用调用方式来传递。 结构类型也可作为函数的返回值类型

温馨提示

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

评论

0/150

提交评论