函数与运算符的重.ppt

上传人:牧羊曲112 文档编号:6093636 上传时间:2023-09-23 格式:PPT 页数:91 大小:249.50KB
返回 下载 相关 举报
函数与运算符的重.ppt_第1页
第1页 / 共91页
函数与运算符的重.ppt_第2页
第2页 / 共91页
函数与运算符的重.ppt_第3页
第3页 / 共91页
函数与运算符的重.ppt_第4页
第4页 / 共91页
函数与运算符的重.ppt_第5页
第5页 / 共91页
点击查看更多>>
资源描述

《函数与运算符的重.ppt》由会员分享,可在线阅读,更多相关《函数与运算符的重.ppt(91页珍藏版)》请在三一办公上搜索。

1、1,第5章 函数,函数与运算符的重载,要点,函数 函数的重载 运算符的重载,2,函数:参数化的子程序;从SP的观点,函数:程序长度;整个程序子任务;从运算的角度,函数:C+提供的用户定义 的运算。运算符:系统提供的运算;作为OOP的C+,类:核心,类=数据+方法,方法/类的函数成员:对数据的运算和处理。,函数在C+中的意义,3,例:按照Cardan公式,计算3次方程x3+px+q=0 的一个实根:,5.1 3次方程求根程序的设计,方法:(1)计算浮点数的立方根的程序作为函数(2)主程序中2次调用该函数(3)计算 迭代公式:rn+1=2/3*rn+y/(3rn2),4,#include#incl

2、udefloat cuberoot(float);/原型void main(void)float p,q,xr;coutpq;float a=sqrt(q/2*q/2+p/3*p/3*p/3);/xr=cuberoot(-q/2+a)+cuberoot(-q/2-a);coutendlThe real root of the equation is xr;,5,/计算:rn+1=2/3*rn+x/(3rn2)float cuberoot(float x)float root,croot;const float eps=1e-6;croot=x;do root=croot;croot=(2*ro

3、ot+x/(root*root)/3;while(abs(croot-root)eps);return(croot);,6,执行结果,7,属性说明 类型 函数名(参数表);,5.2 函数的说明与使用,1.函数说明,函数原型/声明,-指出函数的名称,类型和参数,例:int add(int a,int b);inline void swap(float&,float&);void print(char*);,可省略,8,inline:内联函数 P125static:静态函数 P170virtual:虚函数 P202friend:某类的友元函数 P170,属性说明 类型 函数名(参数表);,可缺省,

4、属性说明,函数的返回类型,标识符,除main()函数和类的构造/析构函数之外,所有函数必须指出返回类型,9,例:/program 7_1.cppclass stack float datamaxsize;int top;public:stack(void);/构造函数 P168 stack(void);/析构函数 P169;stack:stack(void)top=0;coutstack initialized.endl;,10,例:class point/point:平面上一点private:float Xcoord,Ycoord;public:void SetX(float x)Xcoor

5、d=x;/初始化 void SetY(floaty)Ycoord=y;/初始化 float GetX(void)return Xcoord;float GetY(void)return Ycoord;;point p1;point*p2=new point;,11,例:main()print(void)cuberoot(float x)add(int a,int b),属性说明 类型 函数名(参数表);,参数表,空/void/,,例:add(int,int)swap(float&,float&)/引用方式,函数原型中的参数表可忽略参数名,12,程序中某函数的调用语句出现在该函数的定 义前,必须

6、在调用语句之前列出函数原型;,函数原型的使用,/program5_1.cpp#include#includefloat cuberoot(float);void main(void),类定义中,较大的函数成员定义移到类说明 外,该函数的原型列于类说明之中。,13,例:class point/point:平面上一点private:float Xcoord,Ycoord;public:void SetX(float x)Xcoord=x;/初始化 void SetY(floaty)Ycoord=y;/初始化 floatGetX(void)return Xcoord;floatGetY(void)r

7、eturn Ycoord;;,14,例:class Clock/时钟类的定义 public:/外部接口,公有成员函数/函数原型 void SetTime(int NewH=0,int NewM=0,int NewS=0);private:/私有数据成员 int Hour,Minute,Second;void Clock:SetTime(int NewH,int NewM,int NewS)Hour=NewH;Minute=NewM;Second=NewS;,15,函数定义包括函数体,1.函数说明,函数定义,属性说明 类型 函数名(参数表)函数体,与函数原型一致,不可省略参数名,复合语句,函数定

8、义与函数原型的主要区别,16,例:class Clock/时钟类的定义 public:/外部接口,公有成员函数 void SetTime(int NewH=0,int NewM=0,int NewS=0);/函数原型 private:/私有数据成员 int Hour,Minute,Second;/函数定义void Clock:SetTime(int NewH,int NewM,int NewS)Hour=NewH;Minute=NewM;Second=NewS;/函数体,17,2.函数调用,函数调用的两要素,-已定义函数的实际运行,函数名实参表,例:/program5_1.cpp函数的调用实施

9、过程 xr=cuberoot(-q/2+a)+cuberoot(-q/2-a);,(1)搜索同名函数定义;/函数重载(2)核对实参的参数个数,类型,顺序,判定 是否与函数定义中的形参表一致;,例:print(void),18,/计算float cuberoot(float x)float root,croot;const float eps=1e-6;croot=x;do root=croot;croot=(2*root+x/(root*root)/3;while(abs(croot-root)eps);return(croot);,(3)根据参数类型(值/引用参 数)进行值参数的值传递/引用

10、参数的换名;(4)运行函数体代码;(5)返回调用点及函数值。,19,(1)把运行控制从函数体返回到函数调用点;(2)返回数据值。,3.函数的返回,函数的返回完成的任务,例:void main(void).;xr=cuberoot(-q/2+a)+cuberoot(-q/2-a);float cuberoot(float x).return(croot);,20,例:void print()cout“HelloWorld!”;void show()cout“Wonderful C+!”;,函数的返回值,返回void类型,-函数无值返回,未作类型说明的函数,返回int型值,返回数值类型,例:add

11、(int a,int b);/返回int型值 int add(int a,int b);/返回1个值 float cuberoot(float x);,21,函数的返回值,返回数值类型,函数返回的数值1个,以结构/类,数组/对象指针类型方式实现,例:int add(int a,int b);/返回1个值,22,例:#includeclass complex/复数类声明public:/外部接口 complex(double r=0.0,double i=0.0)real=r;imag=i;/构造函数 complex operator+(complex c2);/运算符+重载成员函数 privat

12、e:/私有数据成员double real;/复数实部double imag;/复数虚部;complex complex:operator+(complex c2)return complex(real+c2.real,imag+c2.imag);,23,例:#include int,返回引用类型,24,例:void print(void);int getx();,4.函数的参数,无参函数,-void/空:无参,1/多个参数,例:/对n元int型数组array排序 void sort(int n,char*array);/求3个实数a,b,c中最大者 float max(flaot a,floa

13、t b,float c);,25,1/多个参数,定义中注意参数表的组成。不同的函数根据函数名和参数表来区分,只有二者完全一致才是同一函数。P125,例:函数重载 int abs(int n)return(n0?-n:n);float abs(float f)if(f0)f=-f;return f;double abs(double d)if(d0)return-d;return d;,26,不定个数参数,-参数个数是变化的,例:设计电话计费函数,为了计算通话费,不同 的通话类型(市话,长途,数据与通讯,BP 机等)有不同数目的参数。,27,不定个数参数,处理参数个数不定的途径,例:void s

14、ort(int n,float*a);,例:int f(int a,int b)return a+b*b;int f(int a,int b,int)return a*a+b;f(x,y)调用f(int a,int b)f(x,y,0)f(int a,int b,int),有的C+版本(VC6.0)提供库函数,支持,void abc(int i,);,为了区分函数,允许参数表中包含无名参数,28,C+允许为函数定义可缺省参数,处理参数个数不定的途径,例:int sqrsum(int a,int b,int c=0)/c:可缺省参数 return a*a+b*b+c*c;合法的调用方式:sqrs

15、um(x,y,z);/x,y,z:int型,c=z sqrsum(x+y,x-y);sqrsum(x,y);,参数表中可有任意多个参数为可缺省参数,所有可缺省参数必须列后。调用该函数时,不允许部分缺省:省去全部缺省参数/一个也不省。,29,例:int sqrsum(int a,int b,int c=0,int d=1)/c,d:可缺省参数 return a*a+b*b+c*c+d;调用方式:sqrsum(x,y,z);/,部分缺省 sqrsum(x+y,x-y);/,全部缺省 sqrsum(x,y,m,n);/,全部不缺省,30,5.值调用与引用调用,赋值调用方式,赋值形参:函数定义的参数中

16、,除了说明为 引用(&)的参数外,其余类型的形 参都属于赋值形参。赋值形参在 函数的每次调用时,必须为每个 赋值形参创建新的参数变量。,函数调用时,检查函数名及参数表,为值参分配内存,计算对应的实参表达式,把计算的值赋给刚创建的参数变量,运行函数体。,31,实参表达式:函数调用语句中与赋值形参对应 的实参:指定类型的常量/变量/表 达式。函数调用时,计算该表达 式的值,作为初值赋给刚为赋值 形参创建的参数变量。,赋值调用方式,为赋值形参创建的变量局限于函数体的局部变量,作为该形参的实例,一旦运行完毕,撤消该参数变量。,32,例:定义函数;int multiple3(int n)/n:赋值形参

17、n=n*3;return n;调用函数multiple3 3次:int n=5;/n:变量 coutmultiple3(2)multiple3(n)multiple3(3*n)nendl;/表达式,6 15 45 5,执行结果,33,实参表达式使用只计算值的表达式,实参表达式,例:3*n,x+y,&x,multiple3(n),对可能改变变量值的表达式,注意:当1个函数 有多个赋值形参时,值传递过程中,多个实参 表达式计算的次序。,例:n+,m=s+m*3 realpara(n+,n-);,34,例:void swap(int&a,int&b)/a,b:引用形参 int temp=a;a=b;

18、b=temp;,引用调用方式,引用形参:函数定义的参数表中,&参数名,函数原型:void swap(int,35,(1)函数的调用语句中对应于引用形参的实参必须是同类型的变量,非变量的表达式则不允许;(2)参数传递的内容:地址;(3)函数体的运行中,引用形参起“换名”作用;(4)函数体运行结束,控制转回调用点时,该引用形参与实参变量的对应关系终止。但调用过程中对该实参变量的处理和操作的结果,保留下来。,引用形参不同于赋值形参的参数传递机制的要点,36,例:void swap(int/,37,例:void swap(int/结果x=3,y=5 swap(&y,&z);/结果x=5,y=7,z=3

19、,7,3,3,5,38,例:指针 void swap(int*a,int*b)int temp=*a;*a=*b;*b=temp;int x=5,y=3;swap(/结果x=3,y=5,39,引用调用,表面上与利用指针形参的赋值调用效果相同,实际上优于指针:不需要像指针参数那样通过间址访问。,函数采用引用参数的情形,改变某些变量的值;占内存较多的参数(数组,对象)。,40,int a10=0;int b10=1;int a10=0,1,2,3,4,5,6,7,8,9;int a10;a10=0,1,2,3,4,5,6,7,8,9;/,41,char a23=a,bb;strcpy(a0,a1)

20、;couta0;,42,6.函数的嵌套与递归,函数嵌套,函数的函数体中包含1/多个函数调用语句,嵌套:函数A调用函数B。函数B的定义/原型必 须出现在函数A的定义语句之前。函数A调用函数B:调用A的过程中,调 用B;执行结束返回到A的函数体中。,43,例:void main()fa();,void fa()fb();,嵌套用stack管理,调用层次时空开销,44,函数的递归,函数其函数体中直/间接地自己调用自己,例:间接递归 A调用函数B,函数B又调用函数A,例:float fac(int n)/n!float f=(n2)?1:n*fac(n-1);return f,45,例:快速排序算法

21、int partition(int i,int j,float ai)int m=i;float c=ai;for(int k=i+1;kj;k+)if(akc)am=ak;m+;ak=am;am=c;return m;,46,void Qsort(int f,int l,float a)if(lf)int m=patition(f,l,a);Qsort(f,m,a);Qsort(m,l,a);,47,(1)直/间接递归必须保证在有限次调用后结束;(2)函数调用时系统付出时空间代价,在机能 相同的情形下,非递归程序效率较高。,48,7.内联函数,C+程序中符合条件的函数,函数说明前:inlin

22、e的函数;类内定义的函数成员。,inline 类型 函数名(形式参数表);,例:class point float Xcoord;public:void SetX(float x)Xcoord=x;;,49,编译过程中,inline函数的代码插入到该函数 的各调用点,使程序执行中,每次该函数调 用时不需控制转移,但该函数代码可能有多 个拷贝在目标程序中;把函数体短小而频繁调用的函数说明为inline 函数;编译预处理的宏定义方式,类似于inline函数 的功能。inline函数的方式更方便和可靠。,7.内联函数,50,使用内联函数注意,内联函数体内不能有循环语句和 switch语句;若已在函数

23、原型中指定inline,函 数定义时不能重复给出;递归函数不能被定义成“内联”函数。,51,例:#include#include inline int isnumber(char);void main()char c;int n;n=0;while(c=getchar()!=n)if(isnumber(c)n+;int isnumber(char ch)return(ch=0,52,5.3 函数与运算符的重载,1.重载,-同名不同义,不同情况下表现出不同“行为”,面向对象系统的3大特性之一的多态性通过重 载实现,函数重载:多个函数同名,但执行的操作和 操作对象不同操作符重载:一个运算符,可进行

24、多种不同 含义的解释,进行不同操作,重载,53,例:比较大小:2个整数比较、2个浮点数比 较、.在C+中必须逐个定义不同名的多个函数 目标:系统自动判断,用户只要记住函数 名即可 重载:写多个同名函数,由系统根据操作 数自动判断调用哪个函数,54,2.函数(名)重载,-为了方便程序员的使用,多个不同的函数采 用同一名字,例:int abs(int n)return(n0?-n:n);float abs(float f)if(f0)f=-f;return f;double abs(double d)if(d0)return-d;return d;,不同的数据类型求和,数据的差别很大(整数/向量/

25、矩阵),求和操作差别也大,但完成不同求和操作的函数可以取相同名字,55,例:int abs(int n)return(n0?-n:n);float abs(float f)if(f0)f=-f;return f;main()int a;float b;double c;a=abs(-3);b=abs(-3.20);,56,类,void show(int int_num),void show(double double_num),void show(int nit_ um,float float_um),123,1.23,123,1.23,57,函数重载满足的条件,参数表中对应的参数类型不同参数

26、表中参数个数不同参数表中不同类型参数的次序不同,例:void print(int);/int型 void print(point);/类point的对象 int sum(int,int);int sum(int,int,int);int get(int n,float a);int get(int n,float a,int n);,58,定义同名函数时注意,(1)返回类型不能区分函数,例:float add(int,float);int add(int,float);/,(2)采用引用参数不能区分函数,例:void print(double);void print(double&);/voi

27、d print(const double&);/,59,定义同名函数时注意,(3)有些派生基本类型的参数可以区分同名函数,但需注意,例:int abs(int);unsigned int abs(unsigned int);调用:int a=3,b;unsigned int c=5,d;b=abs(-3);b=abs(3);/二义性 d=abs(3*a);/二义性,二义性:系统对某函数调用语句,有=2个 同名函数与之匹配;找不到与之 匹配的函数定义。,60,定义同名函数时注意,(4)包含可缺省参数时,可能造成二义性,例:int sum(int a,int b,int c=0);int sum(

28、int a,int b);调用:sum(5,3);/二义性,a.寻找1个完全匹配,找到就调用 b.通过内部转换寻找1个匹配,找到就调用 c.通过用户自己定义的转换寻找1个匹配,找到 就调用,匹配重载函数的顺序,61,无准确匹配的函数定义时的处理方式,(1)数组名-指针变量,函数名-函数指针,某类 型变量-const常量的转换,实现匹配?(2)实参类型:低高(字长:短长)进行基本类型-派生类型的转换,可匹配?(3)有无可变个数参数的函数,如有把它归为该 函数。上述尝试性处理后可能出现仍无匹配/匹配不唯 一,可能输出出错信息/错误运行。,定义同名函数时注意,62,(4)同名函数应具有相同的功能,定

29、义同名函数时注意,例:#include int add(int x,int y)coutint,int:;return x+y;double add(double x,double y)coutdouble,double:;return x+y;int add(int x,double y)coutint,double:;return int(x+y);double add(double x,int y)coutdouble,int:;return x+y;,63,void main()coutadd(99,88)endl;coutadd(99.9,88.8)endl;coutadd(99,8

30、8.8)endl;coutadd(99.9,88)endl;,64,3.运算符重载的需要性,问题的提出:C+中,定义一个类就产生一个新类型,类的对象和变量一样可以作为参数传递/函数的返回类型 希望某些运算符能对整个对象操作,而不是C的简单操作 例:+运算符能够实现2个对象间的加 把某些事交给系统去做,用户只要知道相加就可 提出运算符重载,扩充运算符的功能。即:对运算符进 行重载定义,然后使用,由系统自动判断采用哪个具体 的运算符 C+语言的可扩充性,65,例:类A的对象a1、a2、a3,希望:a3=a1+a2;分别把对象a1和a2的各个数据成员值对应相加,然后赋给对象a3 实现途径:对运算符进

31、行重载,66,4.可重载运算符P127,限定符,:条件运算符?:取长度运算符sizeof,不可重载的运算符,可重载的运算符中的情况,1)算术/逻辑/位运算符和关系运算符中的,=,与基本数据类型有关,通过重载,使之用于用户定义的数据类型;,67,可重载的运算符中的情况,2)赋值运算符=,关系运算符=,!=,指针运算 符&和*,下标运算符,涉及的数据类型按 C+规定,不限于基本数值类型,“自动”重载;,3)+/-可作为前/后缀:后缀+的重载函数的原型参数表中增加int型的 无名参数。,前缀+operator+()/作为类成员 operator+()/作为类外函数后缀+operator+(int)/

32、作为类成员 operator+(,int)/作为类外函数,68,前缀+a或a.operator+()operator+(a)后缀+a+或a.operator+(0)operator+(a,0),调用:,前缀+operator+()/作为类成员 operator+()/作为类外函数后缀+operator+(int)/作为类成员 operator+(,int)/作为类外函数,69,例:#include class Increasepublic:Increase(int x):value(x)friend Increase/返回原有对象值,70,5.运算符重载函数的定义,operator,函数名,例

33、:前缀 operator+()operator+(),71,#include class Numberint x;public:Number()x=0;Number(int i)x=i;void disp()coutx=xendl;void operator+()x+;/前置运算符void operator+(int)x+=2;/后置运算符;,72,void main()Number obj(5);obj.disp();+obj;/调用前置运算符 obj.disp();obj+;/调用后置运算符 obj.disp();,73,#include class vectorint x,y;publi

34、c:vector();vector(int i,int j)x=i;y=j;void disp()cout(x,y)endl;void operator+=(vector D)x+=D.x;y+=D.y;void operator-=(vector D)x-=D.x;y-=D.y;,74,void main()vector A(1,2),B(4,2);coutA:;A.disp();coutB:;B.disp();A+=B;coutA+=B:;A.disp();A-=B;coutA-=B:;A.disp();,75,例:#include enum newboolFalse,True;newbo

35、ol operator+(newbool a,newbool b)if(a=False),76,main()newbool b1=True,b2=False,b3=True;b1=b1+b2;coutb1endl;b1=operator+(b1,b2);/b1=b1+b2;coutb1endl;b1=operator-(b3);coutb1endl;b1=(b1+b3)*False;coutb1endl;,77,输出结果,78,运算符重载函数的调用,(1)与原运算符相同的调用方式,(2)一般函数调用方式,例:b1=b1+b2;,例:b1=operator+(b1,b2);,79,5.4 程序实

36、例,1.“三色冰激凌”程序,28种颜色的原料,组合成多少种三色冰激淋:1)P283=28*27*26种;2)C283=P283/3!种。元素数:28,选择数:3。,80,/program 5_2.cpp#include long factorial(int number);void main(void)int i,selections,elements;coutselections;/3 coutelements;/28 double answer=elements;for(i=1;iselections;i+)/P283=28*27*26 answer*=-elements;coutA(el

37、ements+selections-1,selections)=;coutanswerendl;,81,answer/=factorial(selections);/C283=P283/3!cout1)value*=number-;return value;,82,long factorial(int number)if(number=1)return 1;else return number*factorial(number-1);,/n!的递归算法/n!=1 n1,fact(3),fact(2)*,3,fact(1)*,2,=1,83,运行结果,84,2.Hanoi塔问题,有3个立柱A,B

38、,C,A柱上穿有大小不等的圆盘64个,较大的圆盘在下,较小者在上。要求借助于B柱把A柱上的64个圆盘移到C柱,规则:(1)每次只能把一个柱上最上面的圆盘移至 另一个柱的最上层;(2)保持在每个柱上的圆盘较大者在下,较 小者在上。,85,移动前,移动后,86,87,88,89,/program 5_3.cpp#include void hanoi(int,char,char,char);void main(void)int m;coutm;coutendlThe step to movingmdisks:;hanoi(m,A,B,C);/AC,B,90,/显示移盘方案 void move(char from,char to)coutto;void hanoi(int n,char a,char b,char c)if(n=1)/n=1,AC move(a,c);else hanoi(n-1,a,c,b);/AB move(a,c);/AC(最大的盘)hanoi(n-1,b,a,c);/BC,C,A,91,运行结果,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号