《面向对象程序设计 第五章 函数2.ppt》由会员分享,可在线阅读,更多相关《面向对象程序设计 第五章 函数2.ppt(43页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、第五章第五章 函数函数 函数概述函数概述 函数的说明与使用函数的说明与使用5.2 5.2 函数的说明与使用函数的说明与使用五、函数参数传递五、函数参数传递1.传值调用方式传值调用方式例例int mul(int m)m=m*3;return m;调用函数调用函数2次次:int m=5;/变量与形参同名变量与形参同名cout mul(2)mul(m)mendl;执行结果执行结果:6 15 5传值调用是指传值调用是指在发生函数调在发生函数调用时,先计算用时,先计算实参表达式的实参表达式的值,并直接将值,并直接将各实参的值依各实参的值依次赋值给各形次赋值给各形参。参。单向传递,单向传递,即由实参到形即
2、由实参到形参;参;形参的值不形参的值不能影响实参的能影响实参的值。值。#includeint add(int,int);void main()int a,b,c;cin a b;c=add(a,b);cout c=c endl;int add(int i,int j)i+;j+;return(i+j);ab24输出c=85.2 5.2 函数的说明与使用函数的说明与使用五、函数参数传递五、函数参数传递2.引用调用方式引用调用方式 引用引用:引用是给已知的一个变量起的一个引用是给已知的一个变量起的一个别别名名。当建立引用时。当建立引用时,程序程序必须必须用另一个用另一个变量或对象的名字初始化它。对
3、引用变量或对象的名字初始化它。对引用的改动,实际上是对目标的改动。的改动,实际上是对目标的改动。引用定义的格式引用定义的格式&();或者或者&=;5.2 5.2 函数的说明与使用函数的说明与使用五、函数参数传递五、函数参数传递2.引用调用方式引用调用方式说明说明:引用在定义时一定要初始化引用在定义时一定要初始化例例 int a=3;int&m=a;m=m+5;int n=m;对引用的操作就是对被引用对引用的操作就是对被引用 的变量的操作的变量的操作 可以把某个引用赋给一个变可以把某个引用赋给一个变 量,该变量的值就是被引用量,该变量的值就是被引用 的变量值的变量值 引用一旦初始化后不得作为引用
4、一旦初始化后不得作为 其他变量的别名其他变量的别名5.2 5.2 函数的说明与使用函数的说明与使用五、函数参数传递五、函数参数传递在一条在一条语句中声明多个引用语句中声明多个引用:int&x=a,y=b,z=c;注注int&x=a,&y=b,&z=c;int&x,y,z;声明引用变量而不对其进行初始化是个语法错误声明引用变量而不对其进行初始化是个语法错误.int x=3,&y;/Reference variable y must be initialized#include void main()int x=3,&y=x;cout“x=”xn“y=”yendl;y=7;cout“x=”xn“y
5、=”yendl;5.2 5.2 函数的说明与使用函数的说明与使用五、函数参数传递五、函数参数传递2.引用调用方式引用调用方式例例x=3y=3x=7y=7输出结果输出结果:5.2 5.2 函数的说明与使用函数的说明与使用五、函数参数传递五、函数参数传递2.引用调用方式引用调用方式 函数的引用调用:函数的引用调用:调用函数的实参必须要用变量名,将实调用函数的实参必须要用变量名,将实参变量名赋给形参的引用,相当于在被调用参变量名赋给形参的引用,相当于在被调用函数中使用了实参的别名。如函数中使用了实参的别名。如swap(a,b);在函数原型中该参数类型后面加上在函数原型中该参数类型后面加上&,如:,如
6、:void swap(int&x,int&y);5.2 5.2 函数的说明与使用函数的说明与使用五、函数参数传递五、函数参数传递2.引用调用方式引用调用方式 函数的引用调用:函数的引用调用:相比按值调用,相比按值调用,按引用调用对性能有按引用调用对性能有利,因为它消除了复制大量数据的开销。但利,因为它消除了复制大量数据的开销。但按引用调用的安全性较差,因为被调用函数按引用调用的安全性较差,因为被调用函数能够直接访问和修改调用者的数据。能够直接访问和修改调用者的数据。#include void swap(int x,int y)int temp=x;x=y;y=temp;coutx“”yendl
7、;void main()int a=3,b=5;swap(a,b);couta“”bendl;#include void swap(int&x,int&y)int temp=x;x=y;y=temp;coutx“”yendl;void main()int a=3,b=5;swap(a,b);couta“”bendl;在传值调用中,swap()函数中形参值的改变对实参无影响 在引用调用中,有&x=a,&y=b,因此x和a,y和b同时改变,从而达到实参交换的目的输出结果:输出结果:5 35 3 3 5 3 5输出结果:输出结果:5 35 3 5 3 5 3#include int squareBy
8、Value(int);void squareByReference(int&);int main()int x=2,z=4;cout“x=”x“before squareByValuen”“Value returned by squareByValue:”squareByValue(x)n “x=”x“after squareByValuen”endl;cout“z=”z“before squareByReference”endl;squareByReference(z);cout“z=”z“after squareByReference”endl;return 0;int squareByV
9、alue(int a)return a*a;void squareByReference(int&cRef)cRef*=cRef;x=2 before squareByValue Value returned by squareByValue:4x=2 after squareByValue z=4 before squareByReference z=16 after squareByReference 5.2 5.2 函数的说明与使用函数的说明与使用五、函数参数传递五、函数参数传递3.传地址调用方式传地址调用方式*指针运算符,表示指针所指向变量的值指针运算符,表示指针所指向变量的值 int
10、 *p&取地址运算符,用于得到一个对象的地址取地址运算符,用于得到一个对象的地址&iint a;int*ptr;ptr=&a;/将变量将变量a的地址赋值给指针的地址赋值给指针ptr#include void swap(int*,int*);void main()int a=3,b=8;cout a=a ,b=b endl;swap(&a,&b);cout after swapping.n;cout a=a ,b=b endl;void swap(int *x,int*y)int temp=*x;*x =*y ;*y=temp;5.2 5.2 函数的说明与使用函数的说明与使用五、函数参数传递五、
11、函数参数传递传址调用指将实参的地址传递给形参传址调用指将实参的地址传递给形参采用这种方式调用时,实参必须用地址值,形采用这种方式调用时,实参必须用地址值,形参用指针变量参用指针变量发生函数调用时,将实参地址直接传递给相应发生函数调用时,将实参地址直接传递给相应的各形参指针变量的各形参指针变量在函数中通过形参指针可以对实参进行间接读在函数中通过形参指针可以对实参进行间接读写写5.2 5.2 函数的说明与使用函数的说明与使用五、函数参数传递五、函数参数传递3.传地址调用方式传地址调用方式5.2 5.2 函数的说明与使用函数的说明与使用六、函数的嵌套与递归六、函数的嵌套与递归1.函数嵌套函数嵌套:一
12、个函数的函数体中包含一个或多:一个函数的函数体中包含一个或多 个函数调用语句。个函数调用语句。若函数若函数A要调用函数要调用函数B,则函数则函数B的定义的定义 或函数原型必须出现在或函数原型必须出现在A的定义之前。的定义之前。说明说明若函数若函数A在执行过程中调用在执行过程中调用B,则中途将则中途将 程序控制权转到程序控制权转到B,待,待B执行结束后再返执行结束后再返 回到回到A。函数嵌套调用示例函数嵌套调用示例定义一个求定义一个求 bin(n,k)的函数。的函数。分析:分析:定义函数定义函数 fact(m)=m!bin(n,k)=fact(n)/(fact(k)*fact(n-k)由主函数输
13、入数据由主函数输入数据 a、b,求求 bin(a,b)试一下试一下函数嵌套调用示例函数嵌套调用示例#includelong fact(int m)int i;long sum=1;for (i=1;i=m;i+)sum*=i;return sum;long bin(int n,int k)return (fact(n)/(fact(k)*fact(n-k);void main()int a,b;long f1,f2;cout Please input data a and b:a b;f1=fact(a)/(fact(b)*fact(a-b);cout first:bin(a ,b )=f1
14、endl;f2=bin(a,b);cout second:bin(a ,b )=f2 endl;函数嵌套调用示例函数嵌套调用示例#includelong fact(int m)int i;long sum=1;for (i=1;i=m;sum*=i,i+);return sum;long bin(int n,int k)return (fact(n)/(fact(k)*fact(n-k);void main()int a,b;long f1,f2;cout Please input data a and b:a b;f1=fact(a)/(fact(b)*fact(a-b);cout firs
15、t:bin(a ,b )=f1 endl;f2=bin(a,b);cout second:bin(a ,b )=f2 endl;函数嵌套调用示例函数嵌套调用示例#includelong fact(int m)int i;long sum=1;for (i=1;i=m;sum*=i,i+);return sum;long bin(int n,int k)return (fact(n)/(fact(k)*fact(n-k);void main()int a,b;long f1,f2;cout Please input data a and b:a b;f1=fact(a)/(fact(b)*fac
16、t(a-b);cout first:bin(a ,b )=f1 endl;f2=bin(a,b);cout second:bin(a ,b )=f2 endl;函数嵌套调用示例函数嵌套调用示例#includelong fact(int m)int i;long sum=1;for (i=1;i=m;sum*=i,i+);return sum;long bin(int n,int k)return (fact(n)/(fact(k)*fact(n-k);void main()int a,b;long f1,f2;cout Please input data a and b:a b;f1=fact
17、(a)/(fact(b)*fact(a-b);cout first:bin(a ,b )=f1 endl;f2=bin(a,b);cout second:bin(a ,b )=f2 endl;5.2 5.2 函数的说明与使用函数的说明与使用六、函数的嵌套与递归六、函数的嵌套与递归2.函数递归函数递归:即自调用函数,在函数体内部直接:即自调用函数,在函数体内部直接 或间接地自己调用自己。或间接地自己调用自己。例如:下面的程序求例如:下面的程序求n!long fact(int n)if(n=1)return 1;return fact(n-1)*n;5.2 5.2 函数的说明与使用函数的说明与使用
18、六、函数的嵌套与递归六、函数的嵌套与递归2.函数递归函数递归递推阶段递推阶段:将原有问题不断地分解为新:将原有问题不断地分解为新的子问题,逐渐从未知向已知的方向推的子问题,逐渐从未知向已知的方向推测,最终到达已知的条件,即递归结束测,最终到达已知的条件,即递归结束条件,这时递推阶段结束。条件,这时递推阶段结束。递归调用递归调用 的过程的过程回归阶段回归阶段:从已知条件出发,按照:从已知条件出发,按照“递递推推”的逆过程,逐一求值回归,最后到的逆过程,逐一求值回归,最后到达递推的开始处,结束回归阶段,完成达递推的开始处,结束回归阶段,完成递归调用。递归调用。5.2 5.2 函数的说明与使用函数的
19、说明与使用六、函数的嵌套与递归六、函数的嵌套与递归2.函数递归函数递归#include int f(int n)if(n=1)return 1;else return f(n-1)+n;void main()cout“s=”f(4)endl;递归终止条件递归终止条件修改递归条件修改递归条件#include int f(int n)if(n=1)return 1;else return f(n-1)+n;void main()cout“s=”f(4)endl;f(4)f(4)f(4)f(3)f(3)f(2)f(2)f(1)f(4)=f(3)+4f(3)=f(2)+3f(2)=f(1)+2f(4)
20、=6+4=10f(3)=3+3=6f(2)=1+2=31105.2 5.2 函数的说明与使用函数的说明与使用七、内联函数七、内联函数1.为什么要引进内联函数为什么要引进内联函数?#include int isnumber(char);void main()char c;while(c=cin.get()!=n)if(isnumber(c)cout“Digitn”;else cout=0&ch=9)?1:0;#include int isnumber(char);void main()char c;while(c=cin.get()!=n)if (ch=0&ch=9)?1:0)cout“Digi
21、tn”;else cout“Not Digitn”;5.2 5.2 函数的说明与使用函数的说明与使用七、内联函数七、内联函数2.内联函数的定义内联函数的定义inline 类型说明符类型说明符 被调用函数名被调用函数名(形参表形参表)内联函数具有一般函数的特性,它与一般函内联函数具有一般函数的特性,它与一般函数的不同之处仅在于函数调用的处理。内联函数数的不同之处仅在于函数调用的处理。内联函数在调用时,是将调用表达式用内联函数体来替换。在调用时,是将调用表达式用内联函数体来替换。内联函数在开始时仅声明一次。内联函数在开始时仅声明一次。5.2 5.2 函数的说明与使用函数的说明与使用七、内联函数七、
22、内联函数2.内联函数的定义内联函数的定义#include inline int isnumber(char);void main()char c;while(c=cin.get()!=n)if(isnumber(c)cout“Digitn”;else cout=0&ch=9)?1:0;内联函数必须在被调用之前声明或定义。因为内因为内联函数的代码必须联函数的代码必须在被替换之前生成。在被替换之前生成。所以,程序若开始所以,程序若开始时不声明为时不声明为inline,后面有后面有inline也被视也被视为普通函数。为普通函数。内联函数中不能含有复杂的结构控制语句,如switch和循环语句。如果内联
23、函数有这如果内联函数有这些语句,则编译将些语句,则编译将该函数视为普通函该函数视为普通函数那样产生函数调数那样产生函数调用。用。递归函数不能用作内联函数。内联函数只适用于15行的小函数。对一个含有许。对一个含有许多语句的大函数,多语句的大函数,函数调用和返回的函数调用和返回的开销相对来说微不开销相对来说微不足道,没必要用内足道,没必要用内联函数来实现。联函数来实现。八、函数重载八、函数重载 函数重载是指同一个函数名可以对应着多个函函数重载是指同一个函数名可以对应着多个函数的实现,即支持多个不同的函数采用同一名字。数的实现,即支持多个不同的函数采用同一名字。int abs(int);long l
24、abs(long);double dabs(double);C语言语言int abs(int i);long abs(long l);double abs(double d);C+语言语言(要求函数名唯一要求函数名唯一)5.2 5.2 函数的说明与使用函数的说明与使用八八、函数重载、函数重载C+的函数如果在的函数如果在返回类型、参数类型、参数个数、参数顺序上有所不同,则认上有所不同,则认 为是不同的。但重载函数如果仅仅是返为是不同的。但重载函数如果仅仅是返 回类型不同,则是不够的,例如下面的回类型不同,则是不够的,例如下面的 声明是错误的:声明是错误的:说明说明void func(int);)
25、;int func(int););5.2 5.2 函数的说明与使用函数的说明与使用八八、函数重载、函数重载举例说明参数类型不同的重载函数的实现举例说明参数类型不同的重载函数的实现例例1#include int abs(int x)return x0?x:-x;float abs(float x)return x0?x:-x;void main()cout“-10的绝对值是的绝对值是:”abs(-10)endl;cout“-2.5的绝对值是的绝对值是:”abs(-2.5)endl;5.2 5.2 函数的说明与使用函数的说明与使用举例说明参数个数不同的重载函数的实现举例说明参数个数不同的重载函数的
26、实现例例2#include int min(int a,int b)return ab?a:b;int min(int a,int b,int c)int t=min(a,b);return min(t,c);int min(int a,int b,int c,int d)int t1=min(a,b);int t2=min(c,d);return min(t1,t2);void main()coutmin(13,5,4,9)endl;coutmin(-2,8,0)endl;八八、函数重载、函数重载typedef定义的类型只能使之相同于一个定义的类型只能使之相同于一个 已存在的类型已存在的类型
27、,而不能建立新的类型,而不能建立新的类型,所以不能用所以不能用typedef定义的类型名来区分定义的类型名来区分 重载函数声明的参数。例如下面的代码重载函数声明的参数。例如下面的代码 实际上是同一个函数:实际上是同一个函数:说明说明typedef INT int;void func(int x)/void func(INT x)/error5.2 5.2 函数的说明与使用函数的说明与使用八八、函数重载、函数重载 让重载函数执行不同的功能,是不好让重载函数执行不同的功能,是不好 的编程风格。同名函数应该具有相同的编程风格。同名函数应该具有相同 的功能。如果定义一个的功能。如果定义一个abs()函
28、数而函数而 返回的却是一个数的平方根,则程序返回的却是一个数的平方根,则程序 的可读性受到破坏。的可读性受到破坏。说明说明5.2 5.2 函数的说明与使用函数的说明与使用八八、函数重载、函数重载 使用重载,应避免产生二义性。使用重载,应避免产生二义性。说明说明包含包含缺省参数缺省参数时,可能造成二义性。例如时,可能造成二义性。例如:int sum(int a,int b,int c=0);int sum(int a,int b);5.2 5.2 函数的说明与使用函数的说明与使用5.3 5.3 头文件与多文件结构头文件与多文件结构一、头文件一、头文件一个项目文件往往包含多个头文件一个项目文件往往
29、包含多个头文件(.h)和源文件和源文件(.cpp)一般将声明部分或者说明部分(包括类的声明)形成一般将声明部分或者说明部分(包括类的声明)形成.h文件,将函数的定义、类的实现及类的使用等形成文件,将函数的定义、类的实现及类的使用等形成.cpp。/examplech317.h 关于函数原型声明的头文件关于函数原型声明的头文件double cuboid(double x,double y);double cylinder(double h,double r);double spheroid(double r);5.3 5.3 头文件与多文件结构头文件与多文件结构二、多文件结构二、多文件结构一个一个
30、C+C+程序称为一个工程(程序称为一个工程(.dspdsp)一个工程由一个或多个文件组成一个工程由一个或多个文件组成 一个文件可以包含多个函数定义,但一个函数的定义必须一个文件可以包含多个函数定义,但一个函数的定义必须完整地存在于一个文件中完整地存在于一个文件中 一个文件可以被多个应用程序共享一个文件可以被多个应用程序共享计算圆面积和矩形面积计算圆面积和矩形面积myArea.hmyCircle.cppmyRect.cppmyMain.cpp计算圆面积和矩形面积计算圆面积和矩形面积const double pi=3.14;double circle(double radius)return pi
31、*radius*radius;myCircle.cppdouble rect(double with,double length)return with*length;myRect.cppdouble circle(double radius);double rect(double width,double length);myArea.h计算圆面积和矩形面积计算圆面积和矩形面积#include#include myArea.hvoid main()double width,length;cout width length;cout Area of recttangle is:rect(wid
32、th,length)endl;double radius;cout radius;cout Area of circle is:circle(radius)endl;myMain.cpp用指定正文替换程序中出现的标识符用指定正文替换程序中出现的标识符 形式形式#define 标识符标识符 文本文本#undef 功能是删除功能是删除 由由#define定义的宏,使之不再起作用定义的宏,使之不再起作用一、一、宏定义宏定义5.4 5.4 编译预处理编译预处理/calculate.h#define CALCULATE_H /用后续用后续4行正文代替行正文代替CALCULATE_H double cir
33、cle(double radius)const double pi=3.14159;return pi*radius*radius;include指令在编译之前把指定文件包含到该命指令在编译之前把指定文件包含到该命令所在位置令所在位置#include 或或#include 文件名文件名 形式为:形式为:系统头文件系统头文件 二、二、文件包含文件包含5.4 5.4 编译预处理编译预处理自定义头文件自定义头文件 所有编译指令以所有编译指令以#开头,每条指令单独占一行开头,每条指令单独占一行形式形式1#if 常量表达式常量表达式程序段程序段#endif形式形式2#if 常量表达式常量表达式程序段程序
34、段1#else程序段程序段2#endif形式形式3#if 常量表达式常量表达式1程序段程序段1#elif 常量表达式常量表达式2程序段程序段2#elif 常量表达式常量表达式n程序段程序段n#else程序段程序段n+1#endif三、三、条件编译条件编译 5.4 5.4 编译预处理编译预处理形式形式4#ifdef 标识符标识符程序段程序段1#else程序段程序段2#endif形式形式5#ifndef 标识符标识符程序段程序段1#else程序段程序段2#endif三、三、条件编译条件编译 5.4 5.4 编译预处理编译预处理如果标识符被如果标识符被#define定义,定义,且没有执行且没有执行undef语句,则编语句,则编译程序段译程序段1,否则编译程序段,否则编译程序段2,没有程序段,没有程序段2,else可以省可以省略略如果标识符没有被如果标识符没有被#define定定义,则编译程序段义,则编译程序段1,否则编,否则编译程序段译程序段2,没有程序段,没有程序段2,else可以省略可以省略