第三章 高级函数特性.

Slides:



Advertisements
Similar presentations
移动应用软件开发技术 第二讲:C++编程基础
Advertisements

第一章 C语言概述 计算机公共教学部.
第九讲 类与对象 (I)面向对象基础.
第八章 类和对象.
C++程序设计 王希 图书馆三楼办公室.
Introduction to the C Programming Language
第5章 函数与模块化设计 学习目的与要求: 掌握函数的定义及调用方法 理解并掌握参数的传递方法 理解函数的嵌套与递归调用
第5章 函数与预处理 《 C语言程序设计》 (Visual C++ 6.0环境) 本章导读
C++语言程序设计 第四章 类与对象 成都信息工程学院计算机系.
函數(一) 自訂函數、遞迴函數 綠園.
第4章 函数与预处理 4.1 概述 4.2 定义函数的一般形式 4.3 函数参数和函数的值 4.4 函数的调用 *4.5 内置函数
教材 《C++程序设计》.谭浩强. 清华大学出版社 王雪晶
Chap 10 函数与程序结构 10.1 函数的组织 10.2 递归函数 10.3 宏定义 10.4 编译预处理.
If … else 選擇結構 P27.
C 程式設計— 語言簡介 台大資訊工程學系 資訊系統訓練班.
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
第一章 程序的基本结构. 第一章 程序的基本结构 教材及授课结构 本章目标 基本内容 扩展阅读 上机指导 应用举例 习题.
C++ 程式設計— 語言簡介 台大資訊工程學系 資訊系統訓練班.
第七章 函数 目录 有参的加法函数的开发 函数定义的一般形式 函数参数和函数的值 函数的调用
授课老师:龚涛 信息科学与技术学院 2018年3月 教材: 《Visual C++程序员成长攻略》 《C++ Builder程序员成长攻略》
Object-Oriented Programming in C++ 第一章 C++的初步知识
第12章 從C到C++語言 12-1 C++語言的基礎 12-2 C++語言的輸出與輸入 12-3 C++語言的動態記憶體配置
第八章 函数.
第四章 小技巧.
第3讲 C++程序控制结构 3.1 顺序结构 3.2 分支结构 3.3 循环结构 3.4 转向控制 3.5 综合案例分析.
类类型 C++支持的内置类型和操作,如 int i=10; i=i%6; i=i+4;
C++语言程序设计 第二章 C++简单程序设计.
C++大学基础教程 第4章 函数 北京科技大学 信息基础科学系.
谭浩强 编著 中国高等院校计算机基础教育课程体系规划教材 C++程序设计.
切換Dev c++顯示語言 工具->環境選項(V)->介面->language (Chinese TW)
第七章 函数及变量存贮类型 7.1 函数基础与C程序结构 7.2 函数的定义和声明 7.3 函数的调用 7.4 函数的嵌套与递归
第2章 C++流程控制语句 if 语句 switch语句 for语句 while语句 do - while语句 break语句
第0章作业: 教材P12-练习与实践 1.写出用符号’*’输出描绘汉字”大”的流程图。
第1章 概述 本章要点: C语言程序结构和特点 C语言程序的基本符号与关键字 C语言程序的编辑及运行 学习方法建议:
六、函数 教学目标: 函数的概念、定义、调用和返回 带自定义函数的程序设计 递推算法 递归思想及算法实现 函数的参数传递方式 C语言程序设计.
C++面向对象程序设计 谭浩强编著 授课教师:姬广永 QQ: 学习网站:
第二章 基本数据类型及运算 C数据类型概述 基本数据类型 运算符和表达式 混合运算与类型转换 数据的输入输出 顺序程序设计举例.
C++语言程序设计 C++语言程序设计 第五章 函数 第十一组 C++语言程序设计.
C语言大学实用教程 第5章 函数与程序结构 西南财经大学经济信息工程学院 刘家芬
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
第一章 程序设计和C语言 主讲人:高晓娟 计算机学院.
C语言程序示例: 1.输入10个数,按从小到大的顺序排序。 2.汉诺塔问题。.
第10讲 构造函数和析构函数 构造函数 析构函数 This 指针.
1.2 C语言程序的结构与书写规则 一、 C语言程序的总体结构
C程序设计.
函数 概述 模块化程序设计 基本思想:将一个大的程序按功能分割成一些小模块, 特点: 开发方法: 自上向下,逐步分解,分而治之
Oop8 function函式.
物件導向程式設計 CH2.
Chap 5 函数 5.1 计算圆柱体积 5.2 使用函数编写程序 5.3 变量与函数.
7.1 C程序的结构 7.2 作用域和作用域规则 7.3 存储属性和生存期 7.4 变量的初始化
第11章 從C到C++語言 11-1 C++語言的基礎 11-2 C++語言的資料型態與運算子 11-3 C++語言的輸出與輸入
C程序设计.
第一章 C语言概述 教师:周芸.
C语言程序设计 李祥 QQ:
C++语言程序设计教程 第2章 数据类型与表达式 第2章 数据类型与表达式 制作人:杨进才 沈显君.
C++程式設計入門 變數與運算子 作者:黃建庭.
C++语言程序设计 C++语言程序设计 第十章 多态 第十一组 C++语言程序设计.
第二章 类型、对象、运算符和表达式.
C++程序设计基础 主讲人:谢昕 华东交通大学信息工程学院 第十~十二讲 多态性和虚函数 2005年春季学期.
本节内容 函数嵌套调用的内存布局 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
挑戰C++程式語言 ──第9章 函數.
#include <iostream.h>
第四章 函数 丘志杰 电子科技大学 计算机学院 软件学院.
C++语言程序设计 C++语言程序设计 第十章 多态 第十一组 C++语言程序设计.
《数据结构与算法设计》第一部分 面向对象的C++程序设计基础.
第9章 C++程序设计初步 9.1 C++的特点 9.2 最简单的C++程序 9.3 C++的输入输出 9.4 函数的重载
變數與資料型態  綠園.
Chap 10 函数与程序结构 10.1 圆形体积计算器 10.2 汉诺塔问题 10.3 长度单位转换 10.4 大程序构成.
資料!你家住哪裏? --談指標 綠園.
Introduction to the C Programming Language
Presentation transcript:

第三章 高级函数特性

目标 引用 默认参数 内联函数 函数重载

3.1 函数的定义与使用 一个C++程序是由若干个源程序文件构成的,而一个源程序文件是由若干个函数构成。 函数定义的语法形式 类型标识符 函数名(形式参数表) { 语句序列 }

函数示例 如: void display_larger( int x, int y) { if (x<y) cout<<"The larger is : "<<y<<"\n"; else if(x>y) cout<<"The larger is : "<<x<<"\n"; else cout<<"Two values are equal. "<<"\n"; }

函数的定义 在C++中定义函数时注意: (1)函数的形参及类型说明要采用新的ANSI标准,即必须放在函数名后面的括号内。 (2)当形参有多个时,必须用逗号隔开。 (3)如果函数是无参函数,括号也不能省略。 (4)所有的函数都要先定义,后使用(调用)。 (5)不能省略函数值的类型,必须表明该函数的函数值的类型,即使该函数没有返回值,也要注明函数值的类型为void。

函数的参数和函数的返回值 所谓调用函数是指在程序中使用了该函数。 主调函数 被调函数 调用点 1.形式参数和实际参数(形参和实参) 在调用函数时,大多数情况下,主调函数和被调函数之间有数据传递关系。而函数之间的数据传递就是靠函数的参数进行的,而对无参函数的调用,没有数据传递

函数的参数和函数的返回值 在定义函数时,函数名后面括号内的变量名为“形式参数”(形参)。在调用函数时,函数名后面括号内的表达式为“实际参数”(实参)。 例:void main() {int a,b,c; cin>>x>>y; c=max(a,b); cout<<“max is”<<c; } int max(int x,int y) { int z; z=x>y?x:y; return(z); }

函数的参数和函数的返回值 关于形参和实参说明几点: (1)实参可以是变量、常量、或表达式,但必须有确定的值。而形参必须是变量。 (2) 形参变量,只有存在发生函数调用时,形参才被分配存储单元,在调用结束时,形参所占的内存单元被释放。 (3)实参与形参的类型必须一致,否则会发生“类型不匹配”的错误。 (4)实参对形参的数据传递是“值传递”,即单向传递。由实参把数据传给形参,并且存储单元与形参是不同的单元,并将实参对应的值依次传递给形参变量。调用结束后,形参单元被释放,而实参单元保留并维持原值。

函数的参数和函数的返回值 2. 函数的返回值: (1)函数的返回值是通过函数中的return语句获得的,return语句的格式为: (A) 强制程序执行的流程从被调函数返回到主调函数 (B) 给主调函数带回一个确定的函数值 如:int max(int a,int b) { return(a>b?a:b); }

函数的参数和函数的返回值 (2) 函数值的类型:函数返回值的类型就是在定义函数时的函数值的类型。在定义函数时,函数值说明的类型和return语句中的表达式类型不一致时,则以函数类型为准。 (3)如果被调用函数中没有return语句,为了明确表示函数“不返回值”,要用viod定义无类型。 如: viod print() { printf(“c language”); } 这样系统就保证不使函数带回任何值。

函数原型声明 函数声明 函数名 函数返回值的类型 函数的参数个数和类型 函数声明可以不包含参数名

函数的定义与函数声明间的区别 (1)函数的“定义”是一个函数功能的确立,包括指定函数名,函数返回值的类型,形参及其类型,函数体等,它是一个完整的、独立的函数单位。 (2)函数的“说明”则只是对已经定义好的函数的返回值进行类型的说明,它包括函数名,函数类型和一对括号。而不包括形参和函数体。 (3)对函数进行说明的作用是告诉系统,在本程序中将要用到的函数是什么类型,以便在主调函数中按此类型对函数值作相应的处理。

3.2 函数调用 1.函数调用的格式 函数名(实参数) 如果调用的是无参函数,则实参表可略去,但函数的括号不能省. 3.2 函数调用 1.函数调用的格式 函数名(实参数) 如果调用的是无参函数,则实参表可略去,但函数的括号不能省. 如果实参表中有多个参数,之间用逗号隔开,实参的类型、个数应与形参顺序一一对应。 函数通过下列三种方式完成函数调用: (1)函数调用语句:即以一个函数的调用后面加上“;”作为一个语句。如:printf(); (2)函数表达式:即函数出现在一个表达式中,这时要求函数带回一个确定的值以参加表达式的运算。如:c=2*max(a,b);

函数调用 (3)函数参数:以函数的调用作为一个函数的实参。 如:M=max(a,max(b,c)); 2.调用函数时的前提条件 在一个函数中调用另一个函数,需要具备的条件: (1)首先被调用的函数必须已经存在的函数。如果调用库函数,一般还应在本文件的开头用#include命令将调用有关库函数时所需用到的信息包含到本文件来。 (2)如果调用用户自己定义的函数,则必须对被调函数的原型进行说明,函数的原型包括: 函数值的类型标识符 被调用函数名(形参及其类型表); (3)对函数原型的说明,通常放在程序的顶部,也可以存放到一个头文件中,然后利用#include 语句嵌入到程序中。

函数调用的执行过程 main() 调fun() 结束 ① ② ④ ⑥ ⑦ ③ ⑤ 保存: 返回地址 fun() 当前现场 返回 恢复: 主调程序现场 ⑤

函数的嵌套调用 main{} 调fun1() 结束 fun1() 调fun2() 返回 fun2() ① ② ③ ⑦ ④ ⑤ ⑥ ⑧ ⑨ C++语言中函数的定义是平行的、独立的,所以,函 数的定义是不能嵌套进行的,但函数的调用可以。嵌套调用即在调用一个函数的过程中,又调用另一函数。 main{} 调fun1() 结束 fun1() 调fun2() 返回 fun2() ① ② ③ ⑦ ④ ⑤ ⑥ ⑧ ⑨

函数的嵌套调用 在本例中,main函数在执行过程中,调用了函数a,而函数a中又调用了函数b,所以,这就是一种嵌套调用。 要注意:在函数嵌套调调用过程中程序执行的流程和返回点的问题。

函数的递归调用 1.函数递归调用的概念 函数的递归调用就是当一个函数在执行的过程中,出现了直接或间接地调用函数本身的函数调用方式。 下面定义求n!的函数。 long fact(long n) { if (n==1) return 1; return fact(n-1)*n; //出现了函数fact自己直接调用本 } 身的函数调用 要正确地理解函数的递归调用时,程序执行的流程和返回点。

函数的递归调用 递归过程的两个阶段: 递推: 未知 已知 回归: 4!=4×3! → 3!=3×2! → 2!=2×1! → 1!=1×0! → 0!=1 未知 已知 回归: 4!=4×3!=24←3!=3×2!=6←2!=2×1!=2←1!=1×0!=1←0!=1 未知 已知

函数的递归调用 2.函数递归调用的条件 递归调用的条件也是我们在定义一个递归函数时应该遵循的原则。   2.函数递归调用的条件 递归调用的条件也是我们在定义一个递归函数时应该遵循的原则。 (1)必须有完成函数任务的语句。如:上例求n!中的return 1; (2)有一个确定是否能避免递归调用的测试条件。如果条件不满足时就递归调用,否则就不再递归调用。 (3)有一个递归调用语句,并且该递归调用语句的参数应该逐渐逼近不满足条件,以致最后断绝递归。 (4)先测试,后递归调用。在递归函数定义中,必须先测试,后递归调用。也就是说,递归是有条件的,满足了条件后,才可以递归。

函数的参数传递机制 ——传递参数值 在函数被调用时才分配形参的存储单元。 实参可以是常量、变量或表达式。 实参类型必须与形参相符。 函数的参数传递机制 ——传递参数值 在函数被调用时才分配形参的存储单元。 实参可以是常量、变量或表达式。 实参类型必须与形参相符。 传递时是传递参数值,即单向传递。

函数的参数传递——按值传递 函数调用中复制参数的值 函数只能访问自己创建的副本 对副本进行的更改不会影响原始变量 25 100#

例3-11 输入两 整数交换后输出 例3-11 从键盘输入两个整数,交换次序后输出。 #include<iostream.h> 1、值调用 例3-11 从键盘输入两个整数,交换次序后输出。 #include<iostream.h> void Swap(int a,int b); int main() { int x(5),y(10); cout<<“x=”<<x<<“ y=”<<endl; Swap(x,y); cout<<“x=”<< x<<“ y=”<<endl; return 0; } void Swap(int a,int b) { int t; t = a; a = b; b = t; } 运行结果: x=5 y=10 x=5 y=10

a=b; 5 x 10 y a b t=a; t b=t; 在Swap子函数中 返回主函数以后 执行主函数中的函数调用 Swap(x,y); 24

按引用传递 函数调用中传递参数的引用 主要优点 函数可以访问主调程序中的实际变量 提供一种将多个值从被调函数返回到主调程序的机制 100# 25 100# 100

按引用传递——引用的概念 引用是一种特殊类型的变量,可以被认为是另一个变量的别名。 int i, j; int &ri=i; j=10; ri=j; 注意问题: 声明一个引用时,必须同时对它进行初始化。 一旦一个引用被初始化为一个变量的引用时,就始终只能作为这一个变量的别名,不能另做他用。 引用调用 用引用作为形参的函数调用

向函数传递引用 2-1 引用提供对象的别名或可选名 “&”告诉编译器将变量当作引用 void swap(int&a, int& b) { int t = a; a = b; b = t; }

按引用传递——示例 例3-12 void Swap(int&a,int&b) { void Swap(int &a,int &b); #include<iostream.h> void Swap(int &a,int &b); int main() { int x(5),y(10); cout<<“x=”<<x<<“ y=”<<endl; Swap(x,y); return 0; } void Swap(int&a,int&b) { int t; t = a; a = b; b = t; } 运行结果: x=5 y=10 x=10 y=5

t=a; x 5 t x 的别名 a y 10 y 的别名 b a=b b=t; y 的地址

向函数传递引用 2-2 引用就是对象本身 不要认为 引用是指向对象的指针 引用是该对象的副本 大的数据结构按引用传递,效率非常高

返回引用 返回引用不是返回变量的副本 函数头中包含一个“&” int &fn(int &num) { return(num); } void main() int n1, n2; n1 = fn(n2);

常量引用 用于不希望修改对象,以及要把大对象当作输入参数的情况 高效性和安全性 将引用声明为常量,不能再绑定别的对象 double distance(const point& p1, const point& p2); 将引用声明为常量,不能再绑定别的对象 int const &ri = num1;

3.3 函数的默认参数 调用函数时可以不指定全部参数 为可以不指定的参数提供默认值 3.3 函数的默认参数 调用函数时可以不指定全部参数 为可以不指定的参数提供默认值 函数在声明时可以预先给出默认的形参值,调用时如给出实参,则采用实参值,否则采用预先给出的默认形参值。 int add(int x = 5,int y = 6,int z = 3); main( ) { add( ); //所有这三个参数都采用默认值 add( 1,5); //第三个参数采用默认值 add(1,2,3); //不使用默认值 }

参数的默认值 2-1 一旦给一个参数赋了默认值,后续所有参数也都必须有默认值,即默认参数应从右至左逐渐定义。因为调用时实参取代形参是从左向右的顺序。 int add(int x,int y=6,int z=3); //正确 int add(int x=1,int y=6,int z); 调用上面声明的函数 add() , add(1,3); //错误! int add(int x=1,int y, int z=5); 调用上面声明的函数 add() , add(2); //错误! 注:如果遗漏了中间的参数,编译器将报错

注意 默认值的类型必须正确 默认值可以在原型或者函数定义中给出,但不能在两个位置同时给出 建议在原型声明中指定默认值

默认形参值与函数的调用位置 调用出现在函数体实现之前时,默认形参值必须在函数原形中给出;而当调用出现在函数体实现之后时,默认形参值需在函数实现时给出。 例: int add(int x=5,int y=6); void main(void) { add(); //调用在实现前 } int add(int x,int y) { return x+y; } int add(int x=5,int y=6) { return x+y; } void main(void) { add(); //调用在实现后 }

默认参数的优点 如果要使用的参数在函数中几乎总是采用相同的值,则默认参数非常方便 通过添加参数来增加函数的功能时,默认参数也非常有用

3.4 内联函数 声明形式: inline 类型说明符 被调函数名(形参表)

内联函数 2-1 优点 通常的函数调用会节省内存空间,但是会花费一些额外的时间(函数调用所需的时间),而内联函数不是在调用时发生控制转移,而是在编译时将函数体嵌入在调用语句处,因此节省参数传递、控制转移等开销。因此内联函数节省短函数的执行时间 inline float converter(float dollars);

内联函数 2-2 非常短的函数适合于内联 函数体会插入到发生函数调用的地方 fn1() fn1(); 语句; mfunc(); funcy(); main() 重复地 放到函数中的代码 放在内联函数中的代码

注意事项 其定义必须出现在第一次被调用前; 编译器必须先看到函数定义,而不是声明 内联函数体内一般不能有循环语句和switch语句, 通常内联函数是比较简单的函数; 其定义必须出现在第一次被调用前; 编译器必须先看到函数定义,而不是声明 inline double Cal(double r) {return 3.14* r * r;} area=Cal(r1);

例3-14 内联函数应用举例 #include<iostream> using namespace std; inline double CalArea(double radius) { return 3.14*radius*radius; } int main() { double r(3.0); double area; area=CalArea(r); cout<<area<<endl; return 0;

函数重载 具有相同的名称,执行基本相同的操作,但是使用不同的参数列表 函数多态性 C++允许功能相近的函数在相同的作用域内以相同函数名声明,从而形成重载。方便使用,便于记忆。 具有相同的名称,执行基本相同的操作,但是使用不同的参数列表 函数多态性 void display(); void display(const char*); void display(int one, int two); void display(float number);

函数重载 定义:两个以上的函数,取相同的函数名,但是形参的个数或者类型不同,编绎器根据实参和形参的类型及个数的最佳匹配,自动确定调用哪一个函数,这就是函数的重载。 C++允许功能相近的函数在相同的作用域内以相同的函数名定义,从而形成重载。 int add(int x,int y); int add(int x,int y,int z); float add(float x,float y); float add(float a,float b); float add(int x,int y ) ;

函数重载 注意: 1、重载函数的形参必须不同(个数不同或类型不同)。若函数名相同,形参也相同,仅函数返回值类型不同,编译时会被认为是语法错误(函数重复定义)。 int add(int x,int y); int add(int a,int b); 编译器不以形参名来区分 int add(int x,int y); void add(int x,int y); 编译器不以返回值来区分

注意事项 2、不要将不同功能的函数定义为重载函数。以免出现调用结果的误解、混淆。这样不好: int add( int x,int y) { return x+y;} float add(float x,float y) {return x-y;}

函数重载 编译器通过调用时参数的个数和类型确定调用重载函数的哪个定义 只有对不同的数据集完成基本相同任务的函数才应重载

函数重载的优点 不必使用不同的函数名 有助于理解和调试代码 易于维护代码

数据类型不同的重载 参数的类型不同,编译器就能够区分 同一函数名输出任何数据就是重载了输出函数 int square(int); float square(float); double square(double); 同一函数名输出任何数据就是重载了输出函数

参数个数不同的重载 编译器会调用参数匹配的函数 与函数的声明顺序无关 不会考虑返回类型 int square(int); //函数声明 int square(int,int,int); int asq = square(a) //函数调用 int bsq = square(x,y,z) 编译器会调用参数匹配的函数 与函数的声明顺序无关 不会考虑返回类型

函数重载的作用域规则 重载机制只有在函数声明的作用域内才有效 void main() class first { { first object1; second object2; //没有发生函数重载 object1.display(1) object2.display(); } class first { public: void display(int a); }; class second void display();

例3-16重载函数应用举例 编写三个名为add的重载函数,分别实现两整数相加、两实数相加和两个复数相加的功能。 #include<iostream> using namespace std; struct complex { double real; double imaginary; };

void main(void) { int m, n; double x, y; complex c1, c2, c3; int add(int m, int n); double add(double x, double y); complex add(complex c1, complex c2); cout<<"Enter two integer: "; cin>>m>>n; cout<<"integer "<<m<<'+'<<n<<"="<<add(m,n)<<endl;

cout<<"Enter two real number: "; cin>>x>>y; cout<<"real number "<<x<<'+'<<y<<"= "<<add(x,y) <<endl; cout<<"Enter the first complex number: "; cin>>c1.real>>c1.imaginary; cout<<"Enter the second complex number: "; cin>>c2.real>>c2.imaginary; c3=add(c1,c2); cout<<"complex number (" <<c1.real<< ',' << c1.imaginary <<")+("<<c2.real<<',' <<c2.imaginary<<")=("<<c3.real<<',' <<c3.imaginary<<")\n"; }

int add(int m, int n) { return m+n; } double add(double x, double y) { return x+y; } complex add(complex c1, complex c2) { complex c; c.real=c1.real+c2.real; c.imaginary=c1.imaginary+c2.imaginary; return c; }

运行结果: Enter two integer: 3 5 integer 3+5=8 Enter two real number: 2.3 5.8 real number 2.3+5.8= 8.1 Enter the first complex number: 12.3 45.6 Enter the second complex number: 56.7 67.8 complex number (12.3,45.6)+(56.7,67.8)= (69,113.4)

C++系统函数 C++的系统库中提供了几百个函数可供程序员使用。 使用系统函数时要包含相应的头文件。 例如:求平方根函数(sprt)、求绝对值函数(abs)等。 使用系统函数时要包含相应的头文件。 例如:math.h 或 cmath

查找系统函数的使用说明 查编译系统的库函数手册 查联机帮助——VC++6.0联机帮助的使用方法: help/Contents ->(“活动子集”栏)Visual C++ Documentation -> Visual C++ Documentation ->Using Visual C++ -> Visual C++ Programmer's Guide -> Run-Time Library Reference ->Run Time Routines by Category -> Run Time Routines by Category

总结 引用 默认参数 内联函数 函数重载