在面向对象的程序设计中,函数是面向对象程序设计中对功能的抽象算法
Q:函数这么重要,为何要使用函数呢?函数
A:一个较为复杂的系统每每须要划分为若干个系统,而后对这些子系统分别进行开发调试。C与C++语言则体现为函数。函数编好后,能够被重复使用,使用时能够只关心函数的功能和使用办法而没必要关系函数功能的具体实现,这样有利于代码的重用,能够提升代码效率,加强程序的可靠性,也便于分工合做和修改。spa
函数的定义:设计
类型说明赋 函数名(含类型说明的形式参数表) { 语句序列 }
形式参数(简称形参)表的内容以下:3d
type 1 name1,type 2 name 2,…调试
其中name n是形参名。形参的做用是实现主调函数与被调函数之间的关系。code
两个以上的函数,具备相同的函数名,可是形参的个数或者类型不一样,编译器根据实参和形参的类型及个数的最佳匹配,自动肯定调用哪个函数,这就是函数的重载。对象
Q:为何要用这个功能呢?blog
A:若是没有重载机制,那么对不一样类型的数据进行相同的操做也须要定义名称彻底不一样的函数。实是麻烦。
eg:
int add(int x,int y); float add(float x,float y); //与上式形参类型不一样 int add(int x,int y); int add(int x,int y,int z); //与上式形参个数不一样
注意&习惯:不要将不一样功能的函数定义为重载函数,以避免出现对调用结果的误解、混淆。
值传递是指当发生函数调用时,给形参分配内存空间,并用实参来初始化形参(直接将实参的值传给形参)。这一过程时参数值的单向传递过程,一旦形参得到了值便于实参脱离关系,此后不管形参发生了怎么样的改变,都不会影响到实参。
Q:举个栗子吧!
A:举一个经典的例子!交换整数!
#include <iostream> using namespace std; void swap(int a,int b){ int t = a; a = b; b = t; } int main(){ int x=5,y=10; cout<<"x="<<x<<" y="<<y<<endl; swap(x,y); cout<<"x="<<x<<" y="<<y<<endl; return 0; }
分析:因为采用的是值传递,函数调用时传递的是实参的值,是单向传递过程,形参的改变对实参不起做用。
引用是一种特殊类型的变量,能够被认为是另外一个别名,经过引用名与经过被引用的变量名访问变量的效果是同样的。
使用引用时必须注意下列问题。
1)声明一个引用时,必须对它进行初始化,使它指向一个已存在的对象。
2)一旦一个引用被初始化后,就不能改成指向其余对象。
Q:和值传递有什么区别呢?
A:咱们用代码来证实!
#include <iostream> #include <iomanip> using namespace std; void fiddle(int in1,int &in2){ in1=in1+100; in2=in2+100; cout<<"The values are"; cout<<setw(5)<<in1; cout<<setw(5)<<in2<<endl; } int main(){ int v1=7,v2=12; cout<<"The values are"; cout<<setw(5)<<v1; cout<<setw(5)<<v2<<endl; fiddle(v1, v2); cout<<"The values are"; cout<<setw(5)<<v1; cout<<setw(5)<<v2<<endl; return 0; }
分析:子函数fiddle的第一个参数in1时普通的int型,被调用时传递的是实参v1的值,第二个参数in2是引用,被调用时由实参v2初始化称为v2的一个别名。因而在子函数中对参数in1的改变不影响实参,而对形参in2的改变实际上就是对住函数中变量v2的改变。于是返回主函数后,v1值没有改变,而v2值发生了改变。
函数能够直接或间接地调用自身,称为递归调用。
所谓直接调用自身,就是真在一个函数的函数体中出现了对自身的调用表达式。
eg:
void fun1(){ … fun1(); //调用函数自身 }
递归算法的实质是将原有的问题分解为新的问题,二解决新的问题又用到了原有问题的解法。按照这一原则分解下去,每次出现的新问题都是原有问题的简化的子集,而最终分解出来的问题,是一个已知解的问题。这即是有限的递归调用。只有有限的递归调用才是有意义的。
递归的过程有以下两个阶段:
1)递推
将原有问题不断分解为新的问题,逐渐从未知向已知推动,最终达到已知的条件,即递归结束的条件,这时递归阶段结束。
2)回归
从已知的条件出发,按照递推的逆过程,逐一求值回归,最后大道递推的开始处,结束回归的阶段,完成递归阶段。
Q:用递归知识解决汉诺塔问题。
A:ok👌
分析:将n个盘子从A针移到C针能够分解为下面3个步骤
1.将n个盘子从A针移到B针上(借助C针)
2.把A针上剩下的一个盘子移到C针上
3.将n-1个盘子从B针移到C针上(借助A针)
上面三个步骤包含了两个操做:
1.将多个盘子从一个针移到另外一个针上,这是一个递归的过程
2.将1个盘子从一个针上移到另外一个针上
用hanoi函数实现操做1,用move函数实现操做2
代码以下:
#include <iostream> using namespace std; //src针的最上面一个盘子移动到dest针上 void move(char src,char dest){ cout<<src<<"-->"<<dest<<endl; } //把n个盘子从src针移动到dest针,以medium针做为中介 void hanoi(int n,char src,char medium,char dest){ if (n==1) move(src,dest); else{ hanoi(n-1,src,dest,medium); move(src,dest); hanoi(n-1,medium,src,dest); } } int main(){ int m; cout<<"Enter the number of diskes:"; cin>>m; cout<<"the steps to moving"<<m<<" diskes:"<<endl; hanoi(m, 'A', 'B', 'c'); return