数据结构电子教案-深圳大学-自动化课件-ds.ppt

上传人:xin****828 文档编号:15898322 上传时间:2020-09-13 格式:PPT 页数:106 大小:469.56KB
返回 下载 相关 举报
数据结构电子教案-深圳大学-自动化课件-ds.ppt_第1页
第1页 / 共106页
数据结构电子教案-深圳大学-自动化课件-ds.ppt_第2页
第2页 / 共106页
数据结构电子教案-深圳大学-自动化课件-ds.ppt_第3页
第3页 / 共106页
点击查看更多>>
资源描述
1,C+ 编程简介,殷人昆 王 宏,数据结构电子教案,2,C+语言的概要 类、对象、构造函数与析构函数 输入/输出 函数、参数传递与函数返回值 函数名重载与操作符重载 动态存储分配 友元函数与内联函数 结构、联合与类,C+ 编程 简介,3,C+语言概要,C+源于C语言。 1970年,两位程序员Brian Kernighan和Dennis Ritchie首创了一种新的程序设计语言,取名为C语言。 设计C语言的最初目的是编写操作系统。由于其简单、灵活的特点,C语言很快就被用于编写各种不同类型的程序,从而成为世界上最流行的语言之一。,4,C 语言是一个面向过程的语言。随着软件开发技术的进步, 程序员们最终发现, 把数据和施加在其上的操作结合起来,会得到更易于理解的程序,由此产生了面向对象的程序设计思想。 1980年代初,美国 AT return 0;/正常返回 这是一个只包含一个函数的程序,程序的基本元素是数据说明、函数和注释。,6,注释,C+的第一次注释格式源于C语言。注释开始于“/*”,结束于“*/”,在两者之间的任何内容,包括换行符都被编译器忽略。 注意注释符对不可以嵌套。 第一种注释符以“/”开头,它是单行注释符,在它同一行右侧的任何信息都将被认为是注释而由编译器略去。 注意:上面两种注释符的两个标志符/和*,/和/之间不可以分开。,7,#include 语句,C+将一些标准函数和变量说明放在头文件中。头文件中保存所有与标准函数或变量相关的信息,为了使用头文件中定义的变量和函数,必须将相应的头文件include进主程序,作为程序的一部分进行编译。 用户也可以定义自己的头文件,把一些相关的函数和变量组织在一个文件中,当另外的程序要用到这些函数和变量时,可以将该文件作为头文件include进来。,8,#include指令有两种格式: #include #include “头文件名” 第一种文件名在 中指定, 表示该文件存放于系统设定的子目录中, 这类文件一般是由系统给出的, 并已经过编译。 第二种文件名在 “” 中给出,表示该文件存放在当前目录中, 这些头文件通常由用户自己给出。 头文件中可包含其它头文件, 即 #include 可以直接嵌套。,9,C+源程序中还可包括各种编译命令, 这些命令被称为预处理指令, 常用的除 #include外, 还有条件预处理指令 #if、#ifndef 和#endif 等和宏替换指令 #define。 预处理命令对编译器起作用, 它指示编译器在正式编译前做一些预先处理。#include 命令将指示编译器将其后所跟的文件内容插入到当前文件中;#define 定义一个常量或替换宏,它指示编译器在使用该常量或宏的地方替换为其实际内容;#if、#ifndef和 #endif 指示编译器做条件编译。,10,#define 用来定义一个常量或替换宏, 如: #define size 20 /定义一个常量size,其值永远为20 #define MAX(x, y) (x y) ? y : x) /求x, y中的最大值 经过预编译后, 程序中所有出现 size 和 MAX(x, y) 之处都会被 20 和 (x y) ? y : x) 代替,如: int arraysize;int i = MAX(4, 55); 经预编译后会变为 int array20;int i = (4 55) ? 55 : 4);,11,函数原型,下面的程序给出了典型的 C 程序结构,它是“Hello, world”程序的变型。 这个程序由三个文件组成: /* File: hello.h */ char *hello( );/* File: hello.c */# include /*包括sprintf ( )的原型*/# include /*包括malloc( )的原型*/# include /*包括strlen( )的原型*/ # include hello.h /*包括hello( )的原型*/,12,char *hello(name) char *name; char *value;/*返回串 Hello, name. */ value = (char *)(malloc(9+strlen(name); sprintf (value, Hello, %s., name); return value; /* File: main.c */ # include /*包括printf ( )的原型*/ # include hello.h /*包括hello( )的原型*/,13,main(argc, argv)int argc;char *argv ; printf (%s, hello(world);,头文件名字的后缀用“.h”表示,程序文件名字的后缀用“.c”表示。 hello.h:包含 hello函数的原型。main函数可通过“# include”定向到该原型的定义文件,取得对原型的访问性。,14,hello.c:这是hello函数的定义文件。它通过一个string类型的形式参数接受需要打印的 串, 返回一个string类型的值作为打印串。返回类型必须与在#include定向的“.h”文件中所给出的原型的类型匹配。 main.c:这是打印“Hello, world”的主程序,它构造和返回一个欢迎词字符串,其结果通过函数printf打印出来。 C 把函数和数据定义放在后缀为“.c”的代码文件中。在各代码文件中使用后缀为“.h”的include文件, 定义对其它各模块的调用接口。,15,C+的函数特征,特征是函数参数表的描述。 利用特征信息可进行严格的类型检查。它允许编译器检验实际参数的数目是否正确,对应的形参和实参是否相容,函数返回的类型与函数调用的环境是否相容。 它克服了在许多 C 程序的开发中,由于在C 原型中没有定义参数的类型和数量,而造成的实参和形参之间不匹配,函数返回类型与使用之间不匹配等许多缺陷。,16,现用 C+ 语句改写前面的 C 程序。 C+ 程序在“.h”文件中对 hello( ) 使用了函数特征。对于 hello( ) 的原型: 不要求形式参数的名字出现在特征中 参数的数目和类型,以及返回类型,都完整地在函数说明中定义 C+允许在函数说明时, 在括号内直接声明形式参数的类型。,17,/* File: hello.h */char *hello(char *); /* File: hello.cpp */ # include /包含函数sprintf( )的原型 # include /包含函数strlen( )的原型# include “hello.h” /包含函数hello( )的原型 char *hello(char *name) char *value = new char 9 + strlen(name); sprintf (value, Hello, %s., name);return value;,18,/* File: main.cpp */# include /说明输出流对象cout# include hello.h /包含函数hello( )的原型 main(int argc, char *argv ) cout hello(world);,19,C+的数据声明,C+的数据声明将数据名与数据类型联系起来。其主要形式有: 常数值:如25, 13.4, “value is”, 它们的内容保持不变。 常量:数据声明时在变量名前冠以保留字const,如 const int MAX = 500, 可定义 一个常量。其内容在声明时给定,在声明它的程序运行时内容再赋值无效。 变量:数据类型的实例, 在程序执行时可以改变其内容。,20,C+提供两大类数据类型:基本数据类型和复合数据类型。 基本数据类型有 5 种:整型(int)、浮点型(float)、字符型(char)、双精度浮点型(double)和无值(void)。 复合数据类型包括结构(struct)、联合(union)、位域、枚举(enum)、类(class)和用户自定义类型。 还有由基本数据类型和复合数据类型引申而来的数据类型,包括数组、指针、引用等。,21,枚举:是声明一个整型常数序列的方式。例如, 在程序开头做如下声明 enum Boolean FALSE, TRUE 则建立一个Boolean类型。FALSE, TRUE 都是Boolean类型整型常数, 默认值 0 和 1。 指针:存放对象的存储地址,例如 int i = 5; int *np; /np为一个指向整型量的指针 np = /k中存入np所指地址 i 的内容,22,引用:它用来给一个对象提供一个替代的名字。例如 int i = 5; int 此时, j 是一个引用类型, 它代表 i 的一个替代名。当 i 的值改变时, j 的值也跟着改变。当 printf 语句执行后, 打印出的 i 和 j 的值都是7。,23,C+的作用域,在C+中, 每个变量都有一个作用域。区分一个变量时要同时考虑变量名及其作用域。 在函数定义中声明的变量, 仅能在该函数内部有效使用 在类定义中声明的变量, 仅能在该类内部有效使用 在一个段中声明的名字, 也仅能在该段及其子段中有效使用。,24,在整个程序各处都能访问的变量叫做全局变量。如果一个全局变量在文件1中声明,在文件2中使用,那么在文件2中必须使用保留字extern对该变量进行声明。 如果在构成一个程序的两个文件中分别声明了两个同名的全局变量,这两个变量分别代表两个不同实体,此时需在两个文件中分别使用保留字static对变量进行声明。 如果一个段中的局部变量与一个全局变量同名,且还要在此段中使用该全局变量,此时需利用域操作符:访问该全局变量。,25,表达式与操作符,表达式是用来说明简单计算的。C+中的表达式由操作数和操作符组成,它将操作符施加于操作数,最终得到一个结果。结果的数据类型由参加运算的数据类型决定。 a a + b * c + 200 2 * * R (x + y ) / (a b ) 其中操作符执行的先后顺序由它们的优先级和结合性决定。,26,C+提供了很多预定义的操作符,程序员也可以重新定义这些操作符。 算术操作符:+、-、*、/、%。其中*、/、%优先于+、-。括号用来改变计算顺序。计算时,先计算括号内表达式的值,再将计算结果与括号外的数一起计算,如: 4 *(1 + 2)= 4 * 3 = 12 取模操作符(%)用于计算两整数相除后得到的余数,如:22 % 7 = 1。 注意,%只能用于整数相除,不能对浮点数操作。,27,赋值操作符 “=” 将其右侧的表达式求出结果, 赋给其左侧的变量。例如: int value; value = (2 + 3) * 4; 赋值表达式运算的结果是右运算元的值, 而结果类型是左运算元的数据类型, 例如: value = 2.8 * 4 /结果为11, 而不是11.2 可以连续赋值, 但必须保证各运算元的类型相同。它的处理结果是每个运算元的对象值都为最右侧的运算元值,例如: int i, j; i = j = 0; / i, j都赋为0,28,复合操作符: 加a += b 等价于a = a + b 减 a -= b 等价于a = a - b 乘a *= b 等价于a = a * b 除 a /= b 等价于a = a / b 取模 a %= b 等价于a = a % b 左移一位 a = b 等价于a = a b 按位与 a 是声明语句; circum = 2 * PI * radius; 是表达式语句; 它由一个表达式后接一个分号形成。 cout Value; 等都是简单语句。这些语句告知计算机该如何定义变量以及如何执行程序。,33,除简单语句外,C+还定义了一些可以控制程序执行流程的语句, 这些语句提供对控制流的分支和循环功能。 C+中默认, 语句都是顺序执行, 如果碰到分支或循环语句, 顺序执行的规则就要改变。此外,C+中还有一些跳转语句。 有时还有一些语句需要合在一起作为语法结构中的一条语句,这时需要将这些语句用大括号括起来,形成一个复合语句,复合语句不需要以分号终结。,34,if 语句 (二分支选择型),if 语句的一般格式为: if ( 条件表达式 ) 语句; 如果条件表达式的结果为true (非零值),则执行语句语句,否则跳过这段语句。 语句可以有多条, 这时需用大括号 将这些语句括起来, 形成一条复合语句。 if (条件表达式) 语句1; 语句2; ,35,如果希望在条件满足和不满足时分别执行不同语句,则用 else 引入条件不满足时的语句: if (条件表达式) 语句1; else 语句2; 语句1,语句2也可以是复合语句,不过这时的语句不需以分号结尾。 语句1、语句2中又可以出现 if 语句,所以 if 语句可以嵌套,不过这时容易带来语义的歧义性。,36,例 if ( ch = 0 ) if ( ch = 9 ) cout “这是一个数字!”; else cout “这不是一个数字!”; 这时 else 与哪个 if 匹配呢?为解决语义上的这种歧义性,C+中规定,else 总是与最后一个出现的还没有 else 与之匹配的 if 匹配,所以上面一句的 else 与第二个 if 匹配,如果程序员想让它与第一个 if 匹配,可以用大括号将不与 else 匹配的 if 语句括起来,使之成为复合语句。,37,if ( ch = 0 ) if ( ch x2) int temp = x1; x1 = x2; x2 = temp; ,38,Switch 语句 (多分支选择型),switch 语句用于有多重选择的场合, 形式为 switch (表达式) case 值1: 语句组; break; /break可没有 case 值2: 语句组; break; /break可没有 case 值n: 语句组; break; /break可没有 default: 语句组; ; 注意 case 后的数值必须是一个整型的常量表达式,且任意两个选择项不能相等。,39,当 switch 语句执行时, 先计算其后的表达式值, 将表达式的值与后面各 case 关键字后所跟选择常量依次比较。 如果与某一选择常量相等,则执行其冒号后跟的语句。如果和任何选择常量都不等, 则执行 default 子句后的语句 (如果 default 子句存在) 或什么也不做 (如果 default 子句不存在)。 每个case子句都以 break 语句结束。break 子句的作用是终止当前 switch 语句的执行。,40,例: 统计文章中各字母出现的次数。程序每读入一个字符 ch, 根据它的值, 将相应的计数值增 1, 假定英文大小写不区分。 int aCnt = 0 , bCnt = 0 , , zCnt = 0; switch (ch) case a:case A: aCnt+; break; case b:case B: bCnt+; break; / case z: case Z: zCnt+; break; ,41,循环语句,循环语句提供重复处理的能力, 当某一特定条件为 true 时, 循环语句就重复执行, 并且每循环一次, 就会测试一下循环条件, 如果为 false, 则循环结束, 否则继续循环。 C+支持三种格式的循环语句:while、 do和 for 语句。三者可以完成类似的功能,不同的是它们控制循环的方式。,42,while 语句 (先判断循环),while 语句的一般形式为: while (条件表达式) 循环体语句 while 循环先计算条件表达式, 当条件表达式的运算结果为 true 时, 就执行循环体语句。执行一次循环体语句后, 就会重新计算条件表达式, 当表达式的值为 false 时,循环结束。 while 循环可能一次也不执行。,43,下列程序计算输入文件的字符数,并在标准输出上输出文件内容: #include #include main() char ch; int count = 0; /字符数计数器 ifstream infile (data.in, ios:in); while ( infile ,44,do 语句 (后判断循环),do 语句的一般形式为: do 循环体语句 while (条件表达式); do 语句先执行 循环体语句, 然后计算条件表达式是否为 true, 如果是, 则继续执行循环, 否则结束循环。 与 while 语句不同的是,do 循环中的循环体语句至少执行一次, 而 while 语句当条件第一次不满足时循环体语句一次也不执行。,45,对字符计数的程序也可以用do语句实现。 # include # include int main() char ch; int count = 0; /字符个数计数器 ifstream infile (data.in, ios:in); if ( infile ,46,for 语句,for 语句用于预先知道循环次数的情况, 其一般形式为: for ( 初始化语句; 表达式1; 表达式2 ) 循环体语句; 其中初始化语句可以是一条声明或表达式,用于对循环控制变量进行初始化或赋值。 表达式 1 用于控制循环结束, 当它的值为 true 时, 继续循环, 为false 时终止循环。 表达式 2 在每次循环执行后改变循环控制变量的值。,47,具体来说,for 循环的执行过程为: 执行 初始化语句; 计算 表达式 1 的值; 如果 表达式 1 的值为true: 先执行循环体语句; 再执行表达式2; 然后转向步骤 ; 如果表达式1的值为false, 则结束循环。,48,例: 数组初始化 for ( int i = 0; i size; i+ ) arrayi = 0;,49,跳转语句,跳转语句将中断程序的执行,跳转到其他地方继续执行。包括break、continue和goto语句。 break语句 break语句将使程序从当前的循环语句 ( do, while, for ) 内跳转出来, 接着执行循环语句后面的语句。switch 语句中也用到了 break 语句,这时它表示终止当前 switch 语句的执行,接着运行switch 后的语句。,50,continue语句,continue语句也用于循环语句, 它不是结束循环, 而是结束循环语句的当前一次循环,接着执行下一次循环。在 while 和 do 循环中, 执行控制权转至对条件表达式的判断,在 for 循环中, 转去执行表达式2。 goto语句 goto 语句无条件转移程序的执行控制,它总是与一标号(label)相匹配,其形式为: goto 标号;,51,标号是一个用户自定义的标识符, 它可以处于goto语句的前面,也可以处于其后面,但是标号必须与goto语句处于同一个函数中。 标号定义时,由一个标识符后面跟一冒号组成,如: goto next; next: 语句 /标号,52,下面程序要从键盘读入用户输入的数, 对其求和, 当用户输入数0时, 表示输入结束。 #include int main() int sum = 0; int iVal; while (1) /永远循环 cout iVal; if ( iVal = 0 ) break; /循环出口条件 sum += iVal; cout ”The sum : ” sum n; return 0; ,53,下面程序对用户输入的所有正数求和, 如果输入的是负数, 则忽略该数。 int sum = 0; int iVal = 1; while ( iVal != 0) cout iVal; if ( iVal 0 ) continue; sum += iVal; cout “The sum: ” sum n;,54,C+的类,C+的核心部分是类的定义。类定义体现了抽象数据类型的思想。为达到信息隐蔽的原则。规定对类的成员有三级存取: 共有(public) 私有(private) 保护(protected) 在 public 域中声明的数据成员和函数成员(成员函数),程序中其它类的对象或操作都能请求该类的对象执行它们,因此这些数据成员和成员函数构成类的界面部分。,55,在 private 域和 protected 域中声明的数据成员和成员函数构成类的私有部分,只能由该类的对象和成员函数,以及声明为友元 (friend) 的函数或类的对象才能访问它们。 在 protected 域中声明的数据成员和成员函数,还允许该类的派生类访问它们; 在 private 域中声明的数据成员和成员函数,则不允许该类的派生类访问它们。 下面给出一个 point 类的声明。Point 类中 点的表示由两个整数变量 x, y 组成。类的用户不能直接访问它们。,56,#ifndef POINT_H #define POINT_H /In the header file point.h class Point /类定义private: /私有域 int x; /数据成员:点坐标 int y;public: /共有域 Point ( int, int ); /构造函数 Point ( Point /取y坐标,57,Point operator + ( point ); /点加点 Point operator / ( int ); /点除整数 Point operator * ( int ); /点乘整数 int operator ( Point ); /点比较 int operator ( istream #endif,58,为了存取一个点的 x, y 分量, 类提供了两个函数get_x, get_y。这样可用 private 域来保护数据的表示, 防止类的用户直接使用数据的内部表示来编写代码,通过使用存取函数来操作数据来维持类的抽象性。 private 是声明默认的存取级别。 系统开发时, 把类的声明放在头文件中, 成员函数的实现放在源程序文件中。在源程序文件中函数的实现通过作用域设定命令 “:” 而被归属到某一个类。,59,例,对于 Point 类的输出友元函数的实现可以在源程序文件中给出,形为: ostream 这个函数把点 p 的值以 “x, y” 的格式送到 strm 指明的输出流中去。,60,C+中的对象,建立类的对象(亦称为实例化)时采用的方式类似于定义 C 变量的方式,可以自动地,或静态地, 或通过动态分配来建立。 建立一个 Point 类实例的语句是: Point p (6, 3); 自动地 Point q; 自动地 static Point s (3, 4); 静态地 Point *t = new Point(1, 1); 通过动态分配 对象 p、q 和 s 都是Point类的对象。,61,构造函数,当遇到以上的每一个语句时,将隐式地调用一个构造 (constructor) 函数,这个构造函数属于一个与它同名的类。 在Point类的定义中声明了两个构造函数,构造函数的参数用于初始化表达式的值。 例如,当使用声明 Point p(6, 3) 建立 Point 类的对象 p 时,调用了构造函数 Point (int, int);通过以下函数定义, 将其 x, y 分量设定为 6, 3 : Point : Point (int a,int b) x = a; y = b; Point : Point (int a,int b) : x(a), y(b) ,62,构造函数可以定义默认值。例如 Point : Point ( int a = 0, int b = 0 ) : x(a), y(b) 当定义实例时给定初始值, 则该实例以给定初始值来初始化其数据成员 Point p(6, 3); 则有 x = a = 6, y = b = 3 当定义实例时未给出初始值。则该实例以默认值来初始化其数据成员 Point q; 则有 x = a = 0, y = b = 0,63,析构函数,当要放弃对象时,需隐式地调用另一个函数,叫做析构 (destructor) 函数,它属于名字相同的类, 但在名字前面加上了一个“”。例如Point。 为一个类可定义几个构造函数,但只能定义 一个析构函数。当控制要退出自动变量的作用域时, 或当通过 delete 命令释放一个动态分配的变量时, 就要调用析构函数。当main函数执行结束时,将释放静态声明的变量。 一个析构函数用于在删除一个类的对象时做清除工作。,64,C+的输入/输出,在C+中执行输入/输出操作,需用 #include 预处理指令包括一个 头文件。用它可支持C+的流(stream)操作。 “流”是个简单的字符序列。在C+中有两个预定义的类 istream 和 ostream,它们定义了输入流和输出流。 基本输入/输出方式: 键盘屏幕输入/输出 文件输入/输出,65,键盘屏幕输入/输出,在C中有用于定向到键盘输入设备、屏幕输出设备和错误文件的命令 stdin、stdout 和 stderr。 在C+中用 cin,cout 和 cerr 来定义键盘输入类、屏幕输出类和错误信息输出类。 操作符 用于读入类 istream 的一个对象。,66,在下面程序中使用了流 cin ,相继从标准输入设备上输入两个整型变量 a 和 b, 并将它们打印到标准输出设备上。 #include void main ( ) int a, b; cin a b; cout ”a : a “b : b endl; 在输出语句中最后输出的 endl 是C+的IO操作符, 它的用途是输出一个换行符并清空流。,67,C+中的输入/输出可以是自由格式,程序员不需要使用格式化符号来指定输入输出项的类型和顺序。 与其它 C+ 操作符一样,输入输出操作符能够被重载。,68,文件输入输出,C+中的文件输入输出方式如下所示。 在程序开头必须用预处理指令 #include 包含头文件,它定义了类 ifstream、ofstream和 fstream。 要创建一个输入流,必须声明它为 ifstream 类的实例;要创建一个输出流,必须声明它为ofstream 类的实例。 执行输入和输出操作的流必须声明它为 fstream类的实例,69,#include #include #include void main ( ) ifstream inFile; /inFile为输入流对象 ofstream outFile; /outFile为输出流对象 outFile.open ( my.dat, ios : out ); /建立输出文件my.dat char univ = Tsinghua, name10; int course = 2401, number; outFile univ endl; /输出到my.dat outFile course endl;,70,inFile.open(my.dat, ios:in | ios:nocreate); /打开输入文件my.dat if ( !inFile ) cerr name c number; outFile name: name endl; outFile number: number endl; inFile.close( ); outFile.close( ); ,71,ifstream 类、ofstream 类和 fstream 类都是从istream 类和 ostream 类派生出来的; 而类istream 和 ostream 又是从类 ios 派生出来的,因此这些类都可使用类 ios 的所有运算。 在调用打开文件函数 open( ) 时, 函数参数表包括实际文件名和数据流动的方向,函数返回文件的开始地址。系统在存储文件时, 在其末尾添加有文件结束标记。 如果文件未被打开, 则outFile = 0; 如果文件被成功地打开, 则它将代替cout, 将输出引导到文件my.dat 中。,72,在文件打开的操作中,指定的文件模式有以下几种: iso:app:把所有对文件的输出添加在文件尾。它只用于输出文件。 iso:binary:文件以二进制方式打开。此项缺省时文件以文本方式打开。 iso:nocreate:若文件不存在则将导致打开操作失败。 iso:out:表明该文件用于输出。此项可缺省。 iso:in:表明该文件用于输入。此项可缺省。,73,C+中的函数,在C+中有两种函数: 常规函数和成员函数 不论哪种函数, 其定义都包括 4 个部分: 函数名、形式参数表、返回类型和函数体。 函数的使用者通过函数名来调用该函数;调用时把实际参数传送给形式参数表作为数据的输入;通过函数体中的处理程序实现该函数的功能;最后得到返回值作为输出。,74,下面给出一个函数的例子。Max 是函数名,int a 和 int b 是形式参数表,函数名前面的int 是返回类型,在花括号内括起来的是函数体,它给出了函数操作的实现。 int max ( int a, int b ) /函数返回 a 与 b 中的大值 if (a b) return a; else return b; 在C+中所有函数都有一个返回值,或者返回计算结果,或者返回执行状态。,75,如果函数不需要返回值, 可使用 void 来表示它的返回类型。函数的返回值通过函数体中的 return 语句返回。 return 的作用是返回一个与返回类型相同类型的值,并中止函数的执行。 函数返回时可以通过引用方式,参看下面程序, 此时在函数类型后面加上一 个“,76,main ( ) replace(5) = x; cout s; /用x代替Hello后面的空格 char 函数replace( )的返回类型说明为返回一个字符的引用类型, 在函数执行时返回参数 m 指定的 s数组元素的值。main ( )执行时把字符 “x” 送给s5。,77,C+中的参数传递,函数调用时传送给形参表的实参必须与形参在类型、个数、顺序上保持一致。 参数传递有两种方式。一种是传值,这是缺省的参数传递方式; 一种是引用类型。 使用传值方式时,把实参的值传送给函数局部工作区相应的副本中,函数使用这个副本执行必要的功能。这样,函数修改的是副本的值,实参的值不变。,78,使用引用类型方式传递时, 需将形参声明为引用类型,即在参数名前加一个“,79,main ( ) int a = 1, b =2; cout a and b: a b n; swap ( a, b ); /调用时实际参数不需要加 /不需要加 * ,80,一种特殊的引用调用方式叫做常值引用,其格式为 const Type /数据成员 public: Temperature (int hi, int lo) /构造函数 highTemp = hi; lowTemp = lo; void UpdateTemp(float temp); /传值返回 float GetHighTemp( ) const; /常值返回,84,float GetLowTemp( ) const; /常值传值返回 ; void Temperature : UpdateTemp(float temp) if (temp highTemp) highTemp = temp; if (temp LowTemp) LowTemp = temp; float Temperature : GetHighTemp( ) const return highTemp; float Temperature : GetLowTemp( ) const return LowTemp; ,85,C+中的函数名重载,函数名重载允许C+程序中多个函数取相同的函数名, 但其形参或返回类型可以不同。 例如,C标准函数库中有3个标准函数abs( )、labs( )和fabs( ), 分别计算整型数、长整型数和双精度型数的绝对值。在C中因处理的数据类型不同, 必须取不同的函数名。在C+ 中,可以把这 3 个函数都命名为 abs ( ): int abs ( int ); long abs ( long ); double abs ( double );,86,C+的操作符重载,C+提供了一种能力, 可用同一个名字定义多个函数, 这种能力叫做操作符重载。 例如, 可以命名一个函数: clear(* int), 它将一个整数清零。还可以再命名另一个函数 clear(int ),它把一个整数数组清零。,编译器能够比较具有同名的函数的特征,通过识别实参的数目和每个实参的类型,来标识使用于一个特定调用的是哪一个版本的abs( )。,87,在C中,必须使用名字 clearIntArray( ) 和clearInt( ) 来区分这两个函数。在C+中,编译器能够比较同名函数的特征,通过识别实参的数目和每个实参的类型,来标识一个特定调用中用的是哪一个版本的clear。 为了支持面向对象,C+ 提供了双目重载操作符 (如和)。这种操作可使得程序更可读、写得更自然。 例如, 可定义“点(Point)”的运算, 像 p1+p2: 把两个点 (x1, y1) 和 (x2, y2) 相加成一个点 (x1+x2, y1+y2)。,88,p1 p2: 两个点 p1 和 p2 的“小于”关系,表示p1比p2更靠近原点(0, 0)。 p1i: 一个点p(x, y) 除以一个整数 i 的除法 (x/i, y/i)。 可以按以下方式使用重载操作: Point operator + ( Point p ); Point operator / ( int i ); int operator ( Point p ); 使用这些新的操作的表达式如: Point midPoint = ( point1 + point2 ) / 2;或 if ( midPoint referencePoint ) .,89,注意: 每一个这样的操作符在调用时可看成是该操作符左边对象的成员函数。 例如, (point1+point2) 实际上是一个消息。由类Point的实例point1调用成员函数“+”, 该对象的属性确定第一个操作数的值。 函数参数表中指定的Point的实例point2的属性确定第二操作数的值。 这种重载能力允许像使用内建类型 (如int,float) 那样来使用用户自定义类型。与在不允许重载操作的语言中相同的语句比, 这样可以改善程序的可读性。,90,C+的动态存储分配,在C程序中, 使用一个函数 malloc, 为程序分配它所需要的空间,一旦程序执行结束需要返回到它的调用者时,必须释放这个空间。 C+为动态存储分配提供了两个新的命令:new和delete。它们可用于取代 C 中的库函数malloc和free。 在C+中没有无用单元收集,使用new分配的存储必须显式地使用delete释放。,91,操作new要求以被建立对象的类型做为参数,并返回一个指向新分配空间的指针。 作为对比, 在C中, 函数malloc要求它的调用者提供所需存储空间的数量。 例如, 为动态分配一个整数或一个点, 可编写如下语句: int *ip = new int;或 Point *p = new Point; 它们组成了指针变量的声明 (如 * name) 和动态存储分配 ( new 类型 )。,92,Delete 命令必须能够知道 要释放动态分配的是一个数组,还是一个简单变量。 例如,如果已建立下列有 100个点的数组: Point* p = new Point100; 则通过以下命令释放该存储: delete p; 若遗漏了“ ”,则将只释放 p 所指示的第一个元素,将“失去”其它99个点所占据空间,以致不能再复用它们。若使用时元素下标超出100, 程序将会出错且结果不可预测。,93,友元(friend)函数,在类的声明中可使用保留字 friend 定义友元函数。 友元函数实际上并不是这个类的成员函数,它可以是一个常规函数,也可以是另一个类的成员函数。如果想通过这种函数存取类的私有成员和保护成员,则必须在类的声明中给出函数的原型,并在该函数原型前面加上一个friend。 参看Point类的声明, 有两个重载操作符,它们都被声明为友元函数。,94,内联(inline)函数,在函数定义前加上一个inline前缀就成为内联函数。编译程序在编译时将会把这个函数语句直接插入到普通代码中,因而减少了与函数调用和参数传递有关的系统开销。 直接插入代码所需要的空间比不直接插入的调用方式所需要的空间要多,这取决于函数定义的大小。 除了加上inline保留字外, 内联函数的定义 与其它任何函数定义的方式一样。 inline Point operator + (Point p);,95,结构(struct)与类,C+ 扩充了 C 中结构 (struct) 型的功用,加进成员函数以说明一个类 (class)。在 C+ 中 struct 与 class 的区别在于: 在 struct 中, 默认的访问级别是 public。若在 struct 内部自始至终缺省访问级别, 则所有的成员都是共有的。 在 class 中,缺省的访问级别是 private。 除此之外,struct 与 class 是等价的。例如,下面给出定义矩形类的三种等价的类声明。,96,class Rectangle int x1, y1, h, w; public: Rectangle ( ); Rectangle ( ); int GetX ( ); int GetY ( ); void SetX (int x); void SetY (int y); int GetHeight ( ); int GetWidth ( ); ,97,struct Rectangle Rectangle ( ); Rectangle ( ); int GetX ( ); int GetY ( ); void SetX (int x); void SetY (int y); int GetHeight ( ); int GetWidth ( ); private: int x1, y1, h, w; ,98,联合(Union)与类,与结构一样, 用 Union 也可以定义类。 在C+中, Union 可包含函数和变量, 还可包含构造函数和析构函数。 C+的Union 保留了所有C的特性, 主要是让所有的数据成员共享相同的存储区。 与 class 和 struct 相比, Union 可节省存储。与结构相似, Union 中默认存取级别是public。,99,模板 (template),定义:适合多种数据类型的类定义或算法,在特定环境下通过简单地代换,变成针对具体某种数据类型的类定义或算法。 用模板定义用于排序的数据表类 #include template class dataList private: Type *Element; int ArraySize;,100,void Swap (int m1, int m2); int MaxKey (int low, int high); public: dataList (int size = 10) : ArraySize (size), Element (new Type Size) dataList ( ) delete Element; void Sort ( ); friend ostream ,101,类中所有操作作为模板函数的实现 #include “datalist.h” template void dataList : Swap (int m1, int m2) /交换由m1, m2为下标的数组元素的值 Type temp = Element m1; Element m1 = Element m2; Element m2 = temp; ,102,template int dataList : MaxKey (int low, int high) /查找数组Elementlow到Elementhigh /中的最大值,函数返回其位置 int max = low; for ( int k = low+1, k = high, k+ ) if ( Elementmax Elementk ) max = k; return max; ,103,template ostream ,104,template istream ,105,template void dataList:Sort ( ) /按非递减顺序对ArraySize个关键码 /Element0到ElementArraySize-1排序 for ( int i = ArraySize -1; i 0; i- ) int j = MaxKey (0, i); if ( j != i ) swap (j, i); ,106,使用模板的选择排序算法的主函数 #include “selecttm.h” const int SIZE = 10; int main ( ) dataList TestList (SIZE); cin TestList; cout TestList endl; TestList.Sort ( ); cout TestList endl; return 0; ,
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 图纸专区 > 课件教案


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!