C++ 函数

一、函数的作用

函数的出现,让程序的可读性大大增强,同时函数可以被反复调用,这使程序员在编写大型程序的时候更加方便。

二、获得函数的两种方法

1.标准库里的函数

在C++的标准库中,有很多已经“造好的”函数,我们只要#include相应的头文件,就可以在主函数中调用头文件中包含的函数,比如解决数学问题时常用的#include< cmath >,其中就包含了许多数学相关的函数。

我们在包含了头文件< cmath >后,就可以直接使用这些函数了。

2.定义一个属于自己的函数

如果C++标准库中没有自己需要的函数,我们就可以“自定义函数”:

函数的声明:让计算机知道,我们自定义了一个函数,这就是函数的声明(Declare)。

这里需要注意:函数的定义和函数的声明是有一定不同的,函数的声明在最后是有分号的。

函数的声明:

Bool Prime(int x);

函数的定义:

Bool Prime(int x)

{   

​      for(int i=2;i<=x/2;i++){            

​              if(x/i==0)               

​              return false;  

} 

 return true;

}

声明表示该函数存在,而定义表示该函数怎么去运行,在调用函数之前,必须先声明函数

三、函数的三种调用

调用类型 描述
传值调 用 该方法把参数的实际值复制给函数的形式参数。在这种情况下,修改函数内的形式参数对实际参数没有影响。
指针调用 该方法把参数的地址复制给形式参数。在函数内,该地址用于访问调用中要用到的实际参数。这意味着,修改形式参数会影响实际参数。
引用调用 该方法把参数的引用复制给形式参数。在函数内,该引用用于访问调用中要用到的实际参数。这意味着,修改形式参数会影响实际参数。
1.值传递
void  fun( int a)
{
      a=10; //修改参数
}
int  main()
{
int  a=20;
fun(a);  //调用fun函数
cout<<a<<endl;  //输出变量,变量的值没改变
return 0;
}

值传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。

2.地址传递
void changeNumber(int* x);

int main(void)

{	

int a = 10;	

cout << "a = " << a << endl;	

changeNumber(&a);	

cout << "Now a = " << a << endl;	

return 0;

}

void changeNumber(int* x)

{	

*x = *x + 5;

}

这里的代码就是按地址传递,首先在changeNumber()的声明中,使用了int*类型而不是int类型,其次在main()函数调用changeNumber()函数的时候使用的实参是&a而不是a,这就传递了一个地址给changeNumber()函数,这个changeNumber()就可以完成修改a的任务

四、函数重载

函数重载的本质就是多个函数共用一个函数名

使用重载函数的好处:

1、减少对用户的复杂性。
2、这样做减少了函数名的数量,避免了名字空间的污染,对于程序的可读性有很大的好处

例如:
#include<iostream>

using namespace std;

int myabs(int a);  //自定义求绝对值函数

float myabs(float a);

double myabs(double a);

int main()

{    

​      int a=-1,b=2;    

​      float c=-2.2f,d=3.9f;    

​      double e=-3e-9,f=3e6;    

​      cout<<"a="<<myabs(a)<<endl;   

​      cout<<"b="<<myabs(b)<<endl;   

​      cout<<"c="<<myabs(c)<<endl;    

​      cout<<"d="<<myabs(d)<<endl;   

​      cout<<"e="<<myabs(e)<<endl;  

​      cout<<"f="<<myabs(f)<<endl;  

​      return 0;

}

int myabs(int a){   

​      cout<<"int abs"<<endl;   

​      return (a>=0?a:-a);//如果a>=0 则返回a 否则返回-a

}

float myabs(float a){    

​      cout<<"float abs"<<endl;  

​      return (a>=0?a:-a);//如果a>=0 则返回a 否则返回-a

}

double myabs(double a){    

​      cout<<"double abs"<<endl;   

​      return (a>=0?a:-a);//如果a>=0 则返回a 否则返回-a

}

//运行结果

int abs

a=1

int abs

b=2

float abs

c=2.2

float abs

d=3.9

double abs

e=3e-009

double abs

f=3e+006

注意 重载函数的形参必须不同:个数不同或者类型不同。编译程序对实参和形参的类型及个数进行最佳匹配,来选择调用哪一个函数。如果函数名相同,形参类型也相同(无论函数返回值类型是否相同),在编译时会被认为是语法错误(函数重复定义)。

例如:

(1) int   add(int  x,  int  y);

​          float  add(float   x,float   y);<!--形参类型不同-->

  (2)   int   add(int   x,  int   y);

​         int   add(int   x,  int   y,  int   z);<!--形参个数不同-->

不要将不同功能的函数定义为重载函数,以免出现对调用结果的误解、混淆。

例如:

int  add(int  x,  int  y){  return  x+y;}

float  add(float  x,  float  y){  return  x-y;}


五、编写递归函数

什么是递归?

简单的定义: “当函数直接或者间接调用自己时,则发生了递归.”

经典的例子:斐波那契数列

格式:

·F0 = 0
·F1 = 1
·Fn = Fn – 1 + Fn – 2

有了递归的算法, 用程序实现实在再简单不过了:

int F(int n)
{
    if (n < 0)
        return 0;
    if (n == 0 || n == 1)
        return n;
    else
        return F(n - 1) + F(n - 2);
}

从上面的例子中,我们可以看到在有递归算法描述后, 其实程序很容易写, 但是最关键的问题就是, 我们怎么找到一个问题的递归算法呢?

步骤一:将问题分解为更小的问题

步骤二:分解至最小的问题,并通过一个有限的步骤,解决这个问题

如果这两个步骤完成了,那么我们就找到了解决问题的递归算法,接下来只需要用程序将之写出就行了。

posted @ 2019-09-14 23:38  慕慕慕慕  阅读(361)  评论(0编辑  收藏  举报