《《次课函数机制》PPT课件.ppt》由会员分享,可在线阅读,更多相关《《次课函数机制》PPT课件.ppt(37页珍藏版)》请在金锄头文库上搜索。
1、课程进程 第一部分第一部分 第二部分第二部分第三部分第三部分 基础编程基础编程概述;基本编程语句;数据类型;计算表达面向对象编程技术面向对象编程技术类;对象生灭;继承;基于对象编程;多态过程化编程技术过程化编程技术函数机制;性能;程序结构过程化编程之函数机制过程化编程之函数机制C+语言程序设计语言程序设计任课教师:马彦卓任课教师:马彦卓函数和函数机制函数和函数机制函数和函数机制函数和函数机制函数C+C+的的函函数数是是完完成成既既定定任任务务的的功功能能(过过程程)体体,它它涵涵盖盖了了数数学学函函数数和和一一般般过过程程所所以以基基于于过过程程编编程程本本质质上上就就是是基基于于函函数编程。
2、数编程。函数机制一是指程序运行过程中对函数调用的数据管理和处理过程一是指程序运行过程中对函数调用的数据管理和处理过程二是指编程中函数的使用规范它包括二是指编程中函数的使用规范它包括函数参数的属性和传递规则函数参数的属性和传递规则函数返回类型的匹配与审查函数返回类型的匹配与审查函数名字的识别原则函数名字的识别原则函数体效率的选择函数体效率的选择函数体中数据的访问权限函数体中数据的访问权限等等第五章第五章 函数机制函数机制 Chapter 5 Function MechanismContentsContents5.main参数参数 ( The mains Parameters )1.函数性质函数性
3、质( Function Character ) 2.指针参数指针参数 ( Pointer Parameters )3.栈机制栈机制 ( Stack Mechanism )4.函数指针函数指针 ( Function Pointers )6.递归函数递归函数 ( Recursive Functions )7.函数重载函数重载 ( Function Overload )函数机制函数机制1.1.函数性质函数性质函数性质函数性质 ( Function Character )( Function Character )函数:对输入参数负责对输入参数负责, ,埋头做自己的事埋头做自己的事, ,最终返回结果最
4、终返回结果函数组织:通通过过在在函函数数中中进进行行函函数数调调用用来来扩扩展展运运行行的的规规模模, ,层层层层叠叠的函数构成树结构叠叠的函数构成树结构做法:将将若若干干个个函函数数组组织织成成文文件件, ,又又将将若若干干个个文文件件构构成成程程序序的办法来进行编程分工的办法来进行编程分工1.1.函数性质函数性质函数性质函数性质 ( Function Character )( Function Character )跨越数学函数的C+函数,有四种形态 P135返回类型返回类型 func ( func ( 参数列表参数列表 ) ;) ;返回类型返回类型 func ( ) ;func ( )
5、;void func ( void func ( 参数列表参数列表 ) ) ;void func ( ) ;void func ( ) ;1.1.函数性质函数性质函数性质函数性质 ( Function Character )( Function Character )黑盒原则:函数使用者应关注性能,而少去左右实现细黑盒原则:函数使用者应关注性能,而少去左右实现细节节 (P136(P136例例5.1)5.1)int cost ( int n, int m ) return n*10; / 运输运输n次次m斤斤int cost ( int n, int m ) return m*10; / 运输运
6、输m次次n斤斤/ 选选择一择一个最好的个最好的int cost ( int n, int m ) return (nm? m:n)*10; / 保证运输次数最少保证运输次数最少函数的不同实现具有性能的差异。函数的不同实现具有性能的差异。尽量调用尽量调用C+库中的函数,可减少编程量,同时提高总体质量。库中的函数,可减少编程量,同时提高总体质量。void f(Type a); /a为形参为形参void g() Type x; f(x); /x为实参为实参1.1.函数性质函数性质函数性质函数性质 ( Function Character )( Function Character )传值参数:形参是
7、对实参的克隆,克隆必须遵守类型匹传值参数:形参是对实参的克隆,克隆必须遵守类型匹配规则配规则 (P138)(P138)a实体x实体复制Type类型Type类型. . 指针参数指针参数指针参数指针参数 ( Pointer Parameters )( Pointer Parameters )当一个函数对大量数据进行处理时,将所有数据作为实当一个函数对大量数据进行处理时,将所有数据作为实参进行复制参进行复制内存空间和计算资源的大量浪费!内存空间和计算资源的大量浪费!解决方法:利用指针或引用作为参数来传递数据信息。解决方法:利用指针或引用作为参数来传递数据信息。该方法优点:高效该方法优点:高效该方法风
8、险:破坏黑盒性该方法风险:破坏黑盒性综合评定:值得使用,但要谨慎综合评定:值得使用,但要谨慎. . 指针参数指针参数指针参数指针参数 ( Pointer Parameters )( Pointer Parameters )传递指针:传递指针:指指针针参参数数也也是是值值传传递递的的,指指针针值值的的真真正正用用途途是是进进行行数数据据间间访访,以达到操作数据块(大小由之)的目的以达到操作数据块(大小由之)的目的传递引用:传递引用:引引用用参参数数本本质质上上也也是是值值传传递递的的,它它表表现现为为名名字字传传递递,即即以以形形参参的名字来代替实参名字的名字来代替实参名字如如果果实实参参不不是
9、是实实体体名名而而是是表表达达式式,那那么么其其表表达达式式所所对对应应的的临临时时实体取名为形参,并要求其为常量引用实体取名为形参,并要求其为常量引用意义:意义:指指针针和和引引用用参参数数的的存存在在,使使函函数数实实际际上上可可以以访访问问非非局局部部的的数数据据区,函数的黑盒性便名存实亡区,函数的黑盒性便名存实亡但这并非一定坏事,指针是一把双刃剑,或灵巧或邪恶但这并非一定坏事,指针是一把双刃剑,或灵巧或邪恶引用是为了防范指针非安全的无意操作引用是为了防范指针非安全的无意操作void mySort(int* b, int size);void f() int a = 3, 5, 7, 1
10、, 8, 4, 9; mySort(a, sizeof(a)/sizeof(a0);. . 指针参数指针参数指针参数指针参数 ( Pointer Parameters )( Pointer Parameters )传递指针须附带传递单位数据的个数传递指针须附带传递单位数据的个数元素个数元素个数传指针传指针慎之又慎:避免指针越界操作!慎之又慎:避免指针越界操作!. . 指针参数指针参数指针参数指针参数 ( Pointer Parameters )( Pointer Parameters )通过常量性质限通过常量性质限制无意操作带来的意外副作用制无意操作带来的意外副作用 (P143)(P143)v
11、ector add( / 向量加法向量加法 const vector& a, const vector& b) vector c(a.size(); for(unsigned i=0; ia.size(); +i) ci = ai + bi; return c;3.3.栈机制栈机制栈机制栈机制 ( Stack Mechanism )( Stack Mechanism )运行时内存布局运行时内存布局 P145P145栈区进程空间代码区全局数据区堆区执行代码执行代码全局数据、静态数据全局数据、静态数据动态内存动态内存函数数据(局部数据)函数数据(局部数据)3.3.栈机制栈机制栈机制栈机制 ( St
12、ack Mechanism )( Stack Mechanism )未初始化局部数据的不确定性未初始化局部数据的不确定性#includevoid f() int b; / 未初始化未初始化 std:cout”b“n”;/-int main() int a; / 未初始化未初始化 std:cout”a8804248 B=2788048 3.3.栈机制栈机制栈机制栈机制 ( Stack Mechanism )( Stack Mechanism )指针的无约束性指针的无约束性#includeint a=5;int b=6;int main() int* ap=(int*)4202660; *ap=8
13、; std:couta“n”; std:coutint(&b)“n”;5642026604202664ab4202660ap 8 4202664 总结总结:指针的无约束性指针的无约束性,是函数副作用的根源!是函数副作用的根源!4.4.函数指针函数指针函数指针函数指针 ( Function Pointers )( Function Pointers )函数类型:函数类型:函函数数类类型型因因参参数数类类型型、个个数数和和排排列列顺顺序序的的不不同同而而不不同同,也因返回类型的不同而不同也因返回类型的不同而不同函数指针:函数指针:指指向向代代码码区区中中函函数数体体代代码码的的指指针针. .不不同
14、同的的函函数数类类型型, ,其其函数指针也不同函数指针也不同用法:用法:函函数数指指针针经经常常用用作作函函数数参参数数,以以传传递递连连函函数数本本身身都都不不知道的处理过程(函数)知道的处理过程(函数)4.4.函数指针函数指针函数指针函数指针 ( Function Pointers )( Function Pointers )函数指针与指针函数函数指针与指针函数指向函数的指针简称函数指针指向函数的指针简称函数指针定义:定义: int (*gp)(int)初始化:初始化: int g(int); int (*gp)(int)=g;指针函数:返回指针类型的函数指针函数:返回指针类型的函数 in
15、t *gp(int a) int* gp(int a)函数指针:指向函数的指针。函数指针:指向函数的指针。指针函数:返回值为指针的函数。指针函数:返回值为指针的函数。4.4.函数指针函数指针函数指针函数指针 ( Function Pointers )( Function Pointers )不同的函数指针,不能相互赋值不同的函数指针,不能相互赋值 P151P151int g(int);int (*gp)(int) = g; / rightvoid f();void (*fp)();fp = f; / rightgp = fp; / error不不同类型的同类型的函数函数4.4.函数指针函数指针
16、函数指针函数指针 ( Function Pointers )( Function Pointers )函数指针作为参数传递函数指针作为参数传递 ( (函数名看作是函数指针函数名看作是函数指针) )bool lessThanBitSum(int a, int b) int suma=0, sumb=0; for(int x=a; x; x/=10) suma += x%10; for(int x=b; x; x/=10) sumb += x%10; return suma sumb;int main() int a = 33, 61, 12, 19, 14, 71, 78, 59; sort(a
17、a, aa+8, lessThanBitSum); for(int i=0; i8; +i) coutaai ; coutn;12 14 33 61 71 19 59 784.4.函数指针函数指针函数指针函数指针 ( Function Pointers )( Function Pointers )指定函数指针类型,定义函数指针数组指定函数指针类型,定义函数指针数组typedef void (*MenuFun)();/p154 f0507void f1() coutgood!n; void f2() coutbetter!n; void f3() coutbest!n; MenuFun fun=
18、f1,f2,f3;函数指针类型名调用形式:调用形式: fun0() *fun0()5.5.mainmain参数参数参数参数 ( The mains Parameters )( The mains Parameters )程序运行:程序运行:操作系统读入命令以启动程序操作系统读入命令以启动程序重定向命令:重定向命令:操作系统读入命令后,识别并自我消化的参数操作系统读入命令后,识别并自我消化的参数mainmain函数参数:函数参数:操操作作系系统统读读入入命命令令后后,不不能能识识别别参参数数,将将其其直直接接传传递递给所启动的程序给所启动的程序5.5.mainmain参数参数参数参数 ( The
19、 mains Parameters )( The mains Parameters )命令重定向命令重定向 (P158)/ f0509.cpp#includeusing namespace std;int main() for(int a,b; cinab;) couta+b”n”;8 99 1212 345abc.txt17213575.5.mainmain参数参数参数参数 ( The mains Parameters )( The mains Parameters )main函数参数函数参数 (P159)#includeusing anmespace std;int main(int ar
20、gc, char* argv) for(int i=0; iargc; +i) coutargviendl;f0510 a1 a2 a3 a1a2a36.6.递归函数递归函数递归函数递归函数 ( Recursive Functions )( Recursive Functions )形式上:形式上:一一个个正正在在执执行行的的函函数数调调用用了了自自身身( (直直接接递递归归).).或或者者, ,一一个个函函数数调调用用了了另另一一个个函函数数, ,而而另另一一个个函函数数却却调调用用了了本本函数函数( (间接递归间接递归) )本质上:本质上:程程序序在在运运行行中中调调用用了了相相同同代代码
21、码实实体体的的函函数数, ,却却在在函函数数栈栈中中重重新新复复制制了了该该函函数数的的整整套套数数据据, ,由由于于每每套套数数据据中中的的参参数数也也许许不不同同, ,导导致致了了计计算算条条件件发发生生变变化化,使使得得函函数得以逐步逼近终极目标而运行数得以逐步逼近终极目标而运行递归的条件递归的条件 P1636.6.递归函数递归函数递归函数递归函数 ( Recursive Functions )( Recursive Functions )递归函数可以转换为非递归函数递归函数可以转换为非递归函数例如,求最大公约数例如,求最大公约数long gcd1(int a, int b) / 递归版
22、递归版 if(a%b=0) return b; return gcd(b, a%b);/-long gcd2(int a, int b) / 非递归版非递归版 for(int temp; b; a=b, b=temp) temp = a%b; return a;/-7.7.函数重载函数重载函数重载函数重载 ( Function Overload )( Function Overload )函数重载:函数重载:一一组组概概念念相相同同,处处理理对对象象(参参数数)不不同同的的过过程程,出出于于方方便便编编程程的的目目的的,用用同同一一个个函函数数名名字字来来命命名名的的技技术术称称为函数重载为函
23、数重载参数默认:参数默认:一一个个函函数数,既既可可以以严严谨谨和和地地道道的的调调用用,也也可可以以省省略略参参数数,轻轻灵灵地地调调用用,达达到到此此种种方方便便编编程程目目的的的的技技术术称称为为参数默认参数默认重载与参数默认:重载与参数默认:它它们们都都是是通通过过参参数数的的变变化化来来分分辨辨处处理理任任务务的的不不同同如如果果参参数数决决定定了了不不同同的的处处理理过过程程,则则应应重重载载,否否则则参参数数默认更简捷一些默认更简捷一些7.7.函数重载函数重载函数重载函数重载 ( Function Overload )( Function Overload )重载是不同的函数,以
24、参数的类型,个数和顺重载是不同的函数,以参数的类型,个数和顺序来分辨序来分辨P167P167void print(double);void print(int);void func() print(1); / void print(int); print(1.0); / void print(double); print(a); / void print(int); print(3.1415f); / void pirnt(double); 7.7.函数重载函数重载函数重载函数重载 ( Function Overload )( Function Overload )参数默认是通过不同参数来分辨
25、一个函数调用参数默认是通过不同参数来分辨一个函数调用中的行为差异中的行为差异void delay(int a = 2); / 函数声明时函数声明时int main() delay(); / 默认延迟秒默认延迟秒 delay(2); / 延迟秒延迟秒 delay(5); / 延迟秒延迟秒void delay(int a) / 函数定义时函数定义时 int sum=0; for(int i=1; i=a; +i) for(int j=1; j3500; +j) for(int k=1; k100000; +k) sum+;7.7.函数重载函数重载函数重载函数重载 ( Function Overlo
26、ad )( Function Overload )默认参数的规则默认参数的规则 P169P169默认参数值总是在函数声明时描述的,声明默认参数值总是在函数声明时描述的,声明定义同时存在时,默认参数只能置身于声明定义同时存在时,默认参数只能置身于声明中中函数参数默认值只能从后往前设置函数参数默认值只能从后往前设置调用时的实参按位置解析,默认实参只能从调用时的实参按位置解析,默认实参只能从后往前逐个替换尾部的缺漏后往前逐个替换尾部的缺漏7.7.函数重载函数重载函数重载函数重载 ( Function Overload )( Function Overload )无名参数无名参数函数声明和定义中,都可
27、以省略形参名称。函数声明和定义中,都可以省略形参名称。P170P170void point(int a, int); /声明时省略了第二个形参名声明时省略了第二个形参名void point(int a, int )counta32) for (int i=s.size(); i=33; i-, j+) /一种按位二进制一种按位二进制-十进制转换方法十进制转换方法 high32Int *=2; high32Int +=sj-0; /待续待续/续前续前 bitset bitvec(s.substr(max(s.size()-32,0); /利用利用bitset类直接二进类直接二进制制-十进制转换的
28、方法十进制转换的方法low32Int=bitvec.to_ulong();/ UINT64 i64Int=high32Int*pow(2,32)+low32Int; /标准标准C+已经可以支持已经可以支持64位数,位数,但但VC9以下的版本不支持以下的版本不支持/ couti64Intendl;double valueDoubleValue=high32Int*pow(2.0,32)+low32Int; /直接用直接用double型变量记录该值,由于型变量记录该值,由于double型变量精度的限制,结果不能保证正确型变量精度的限制,结果不能保证正确coutfixedsetprecision(0
29、)valueDoubleValueendl;double high32IntDoubleValue=high32Int*pow(2.0,32); /用用double型变型变量记录其高位,再专门用量记录其高位,再专门用int记录其低位,这样才可以精确表达记录其低位,这样才可以精确表达unsigned int highDecInt=(high32IntDoubleValue+low32Int)/1e9;unsigned int low9DecInt=(static_cast(high32IntDoubleValue- static_cast(high32IntDoubleValue/1e9)*1e9)+low32Int%1000000000)%1000000000;highOctInt?(couthighOctIntlow9OctIntendl):coutlow9OctIntendl;return;