plague0

导航

C++第二次作业

一、 为什么要使用函数

 

  1.  函数可以重复使用,使用时可以只关心函数的功能和使用方法而不必关心函数功能的具体实现,这样有利于代码重用;

 

  2.  使用函数也可以提高开发效率,便于分工合作;

    

     eg:现在需要设计一个规模很大的程序,它有几千项功能,把这些功能都编写在一个主函数里就只能由一个人来编写,因为每个人解决问题的思路是不同的,而且在主函数中的变量名是不能重复的,只有编写者自己知道哪些变量名是可以使用的。这样一来,没有一年半载,这个程序是无法完成的。果我们把这几千项功能分拆为一些函数,分给几百个人去编写,那么用不了几天时间这些函数就都能够完成了。最后用主函数把这些完成的函数组织一下,一个程序很快就完工了。

 

  3.  使用函数可以增加程序的可读性;

 

    eg:现在要设计一个“学生信息处理程序”,需要完成四项工作,分别是记录学生的基本情况、学生成绩统计、优秀学生情况统计和信息输出。如果我们把四项工作全都写在主函数里面,那么我们就很难分清那一段代码在做什么。多层次的缩进和不能重复的变量名给我们阅读程序带来了困难。如果我们为每一个功能编写一个函数,那么根据函数名每个函数的功能就很清晰了。如果我们要修改某一个函数的功能,其他的函数也丝毫不会受到影响。

 

  4.  使用函数可以增强程序的可靠性,也便于修改和维护。

 

 

二、 为什么要用函数重载

 

  1. 函数重载:函数重载是函数的一种特殊情况,C++中允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(包括参数个数,参数类型和参数顺序)必须不同,常用来处理实现功能类似但数据类型不同的问题。简单理解就是“一物多用”。

   eg:

    ①  类型不同;

      比如int类型的加法和float类型的加法函数,不用重载可能要这么写 int addInt(int a,int b);   float addFloat(float a, float b); 调用时同样要用不同的函数名调用。但是用了重载,就都只要用add函数名了,也不用操心传进去的是int还是        float类型的参数。

      int add(int x,int y);

      float add(double x, double y);

    ②  个数不同

      int add(int x, int y);

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

 

三、 什么是值传递

 

  1.      值传递:单向传递,形参只是得到实参的值,它和实参是两个不同的对象,不会互相影响,改变形参,不影响实参。

 

    例:

 #include<iostream>
 2 using namespace std;
 3 void Swap(int, int);
 4 
 5 int main()
 6 {
 7     int a = 1, b = 2;
 8     cout << "a的值为:" << a << "b的值为:" <<b<<endl;
 9     Swap(a, b);
10     cout << "a的值为:" << a << "b的值为:" <<b<<endl;
11 }
12 
13 void Swap(int x, int y)
14 {
15     int temp;
16     temp = x;
17     x = y;
18     y = temp;
19     cout << "Swap函数中a的值为:" << x << "Swap函数中b的值为:" << y << endl;
20 }

 

运行结果:

    

 

    从上面可以看出,主函数声明了两个全局变量a,b并对其赋值1,2;通过函数Swp()函数调用之后,在函数内部将a和b的值交换了,使得函数内,a=2,b=1;但是,这个过程并没有改变全局变量a和b的值。

 

    分析:

      函数Swap()被调用前,实参a和b有自己的存储空间,并且有自己的初始值。当调用函数Swap()时,为形参(即函数的参数)x和y分配存储空间,并将a和b的值复制过来,函数执行过程中,将x和y的值进行交换,当函数执行结束之后,x和y所占用的存储空间将被释放,这种传递的方式,并不会对实参a和b的值产生影响,此即为值传递。

 

 例2:在下列原型所示的C++函数中,按“传值”方式传递参数的是(   )

A.     Void f1(int x);    B.void f2(int *x);   C.void f3(const int *x);   D.void f4(int &x);

 

答案:A

 

解析:函数参数的3种传递方式:①将变量名作为形参和实参,即传值方式;②传递变量指针;③引用形参。其中B、C选项都是传递变量指针,D选项为引用形参,所以本题答案为A。

 

 

 

四、 什么是地址传递

 

  1.  地址传递:就是当调用一个过程时,是把实参变量的内存地址传递给被调用过程的形参,也就是说形参与实参使用相同地址的内存单元。因此当在被调用过程中改变形参的值,就等于改变了实参的值。

 

    例:

 1 void Swap2(int *p, int *p) 
 2 { 
 3   int temp=*p; 
 4   *p=*p; 
 5   *p=temp; 
 6   print(“*p=%d, *p=%d\n”, *p, *p); 
 7 }  
 8  
 9 int main() 
10 { 
11   int a=2; 
12   int b=7; 
13   swap2(&a,&b); 
14   Print(“a=%d, b=%d\n”, a, b); 
15 } 

 

 

输出结果:

   *p=7, *p=2

   a=7, b=2

  分析:

    在这个程序中,指针变量作参数,在Swap2函数里,隐含地存在p=&a; p=&b;这两条语句,表示a的地址代入到了p,b的地址代入到了p。虽然传送的是变量的地址,但实参和形参之间的数据传递仍然是单向的“值传递”,即调用函数不可能改变实参指针变量的值。但它不同于一般值传递的是,它可以通过指针间接访问的特点来改变指针变量所指变量的值,最终达到改变实参的目的。

 

五、 如何编写递归函数

 

  1.  什么是递归

 

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

 

    例:通过递归来计算长度

1 size_t length(const char *str)
2  {
3  if (*str == 0) { 
4 return 0;
5  }
6 return length(++str) + 1;
7  }

 

    2.  使用递归

    经典的例子就是斐波那契数列, 在数学上, 斐波那契数列就是用递归来定义的:

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

 

     注:

      在编写递归函数时要注意,函数中的局部变量和参数只是局限于当前调用层,当递推进入“简单问题”层时,原来层次上的参数和局部变量便被隐蔽起来。在一系列“简单问题”层,它们各有自己的参数和局部变量。

      由于递归引起一系列的函数调用,并且可能会有一系列的重复计算,递归算法的执行效率相对较低。当某个递归算法能较方便地转换成递推算法时,通常按递推算法编写程序。例如上例计算斐波那契数列的第n项的函数fib(n)应采用递推算法,即从斐波那契数列的前两项出发,逐次由前两项计算出下一项,直至计算出要求的第n项。

posted on 2019-09-15 13:51  plague0  阅读(202)  评论(0编辑  收藏  举报