1.4 函数初识——入门

from http://www.learncpp.com/cpp-tutorial/14-a-first-look-at-functions/

一个函数是有许多语句的顺序组合用来完成一项特殊的功能。你已经知道每个程序都需要一个入口函数,main()。但是,大多数程序中含有更多的函数,它们的工作方式与main类似。

通常你的程序需要中断正在执行的语句暂时去处理一些其他的事情。在现实生活中,你经常这么做。举个例子,当你记起你需要打个电话的时候,你也许正在读一本书。你放好书签,打电话,当你打完电话后,再继续读你的书。

C++程序的工作方式类似这么一个过程。当一个程序遇到一个函数调用的时候,会顺序的执行函数中的语句。函数调用就是告诉CPU终端当前的函数,执行其他的函数。CPU在当前执行点放置一个“书签”,然后执行调用函数中的语句。当这个调用函数执行完成后,CPU又返回到原来放置书签的地方,恢复执行。

这里有个新函数声明和调用的例子:

   1: //#include <stdafx.h> // Visual Studio users need to uncomment this line
   2: #include <iostream>
   3:  
   4: // Declaration of function DoPrint()
   5: void DoPrint()
   6: {
   7:     using namespace std;  // we need this in each function that uses cout and endl
   8:     cout << "In DoPrint()" << endl;
   9: }
  10:  
  11: // Declaration of main()
  12: int main()
  13: {
  14:     using namespace std;  // we need this in each function that uses cout and endl
  15:     cout << "Starting main()" << endl;
  16:     DoPrint(); // This is a function call to DoPrint()
  17:     cout << "Ending main()" << endl;
  18:     return 0;
  19: }

 

这个程序会产生下列输出:

Starting main()

In DoPrint()

Ending main()

 

这个程序从main()函数的顶端开始执行,第一行执行打印出 Starting main()。第二行是调用DoPrint函数。在这个点,main函数中的执行语句中断,CPU掉到DoPrint()函数。DoPrint函数的第一行被执行输出 In DoPrint()。当DoPrint函数执行完后,main函数恢复执行。因此,main函数中的下个语句被执行输出 Ending main()。

函数能够被多次调用:

   1: //#include <stdafx.h> // Visual Studio users need to uncomment this line
   2: #include <iostream>
   3:  
   4: // Declaration of function DoPrint()
   5: void DoPrint()
   6: {
   7:     using namespace std;
   8:     cout << "In DoPrint()" << endl;
   9: }
  10:  
  11: // Declaration of main()
  12: int main()
  13: {
  14:     using namespace std;
  15:     cout << "Starting main()" << endl;
  16:     DoPrint(); // This is a function call to DoPrint()
  17:     DoPrint(); // This is a function call to DoPrint()
  18:     DoPrint(); // This is a function call to DoPrint()
  19:     cout << "Ending main()" << endl;
  20:     return 0;
  21: }

 

函数产生如下的结果:

Starting main()
In DoPrint()
In DoPrint()
In DoPrint()
Ending main()

在这个例子中函数main中断了三次。

main函数并不是惟一一个能够购调用其他函数的函数。在下面的例子中,DoPrint()函数调用了第二个函数,DoPrint2()。

   1: //#include <stdafx.h> // Visual Studio users need to uncomment this line
   2: #include <iostream>
   3:  
   4: void DoPrint2()
   5: {
   6:     using namespace std;
   7:     cout << "In DoPrint2()" << endl;
   8: }
   9:  
  10: // Declaration of function DoPrint()
  11: void DoPrint()
  12: {
  13:     using namespace std;
  14:     cout << "Starting DoPrint()" << endl;
  15:     DoPrint2(); // This is a function call to DoPrint2()
  16:     DoPrint2(); // This is a function call to DoPrint2()
  17:     cout << "Ending DoPrint()" << endl;
  18: }
  19:  
  20: // Declaration of main()
  21: int main()
  22: {
  23:     using namespace std;
  24:     cout << "Starting main()" << endl;
  25:     DoPrint(); // This is a function call to DoPrint()
  26:     cout << "Ending main()" << endl;
  27:     return 0;
  28: }

 

产生的输出如下:

Starting main()
Starting DoPrint()
In DoPrint2()
In DoPrint2()
Ending DoPrint()
Ending main()

 

返回值

如果你还记得,但main函数执行完成后,它使用return语句返回一个值给操作系统。你写的函数也能够返回一个数值给调用者。我们通过在函数声明中改变函数的返回类型来实现。返回类型为void意味着函数没用返回一个值。返回类型为int意味着函数返回整型给调用者。

   1: // void means the function does not return a value to the caller
   2: void ReturnNothing()
   3: {
   4:     // This function does not return a value
   5: }
   6:  
   7: // int means the function returns an integer value to the caller
   8: int Return5()
   9: {
  10:     return 5;
  11: }

 

让我们在程序里使用这些函数:

   1: cout << Return5(); // prints 5
   2: cout << Return5() + 2; // prints 7
   3: cout << ReturnNothing(); // This will not compile

 

在第一个语句中,Return5被执行,函数返回5给调用者,然后再输出这个值。

在第二个语句中,Return5被执行,函数返回5给调用者。表达式5 + 2产生7。7在传到cout。

在第三个语句中,ReturnNothing()返回void。将void传给cout是不合理的,当你编译这行的时候,编译器将会产生一条错误。

一个通常被问到的问题是,“我的函数能否通过return语句返回多个值呢?”这个回答是,不能。函数通过return语句只能返回一个值。但是,存在解决这个问题的方法,我们会在深入了解函数的章节中讨论。

 

返回到main函数

现在,你已经了解了main函数如何执行的基本概念。当一个程序执行的时候,操作系统产生一个main函数的调用。执行转到main函数的顶部。main函数中的语句被顺序执行。最后,main函数返回一个整型值给操作系统。这是main函数声明为int main()的原因。

一些编译器对于void main()的声明不会给出错误信息。技术上来讲,这是不合理的。当编译器看到void main()函数时,它被解释为:

   1: int main()
   2: {
   3:     // your code here
   4:     return 0;
   5: }

你应该将main函数声明为int型,当你返回一个值时应该是0(当出现错误的时候,返回其他的整数)。

 

参数

在返回值的部分,你了解到函数能够返回一个值给调用者。参数是允许调用者将信息传递给函数。这允许写成的函数能够完成一般化的任务,不必担心使用的特殊的值,将确切的变量的值交给调用给予。

通过例子能够更好的理解。这里有个简单的例子,两个参数相加,返回和:

   1: //#include <stdafx.h> // Visual Studio users need to uncomment this line
   2: #include <iostream>
   3:  
   4: // add takes two integers as parameters, and returns the result of their sum
   5: // add does not care what the exact values of x and y are
   6: int add(int x, int y)
   7: {
   8:     return x + y;
   9: }
  10:  
  11: int main()
  12: {
  13:     using namespace std;
  14:     // It is the caller of add() that decides the exact values of x and y
  15:     cout << add(4, 5) << endl; // x=4 and y=5 are the parameters
  16:     return 0;
  17: }

当add函数被调用的时候,x被赋值为4,y被赋值为5.函数执行x+y,结果为9,将这个值返回给调用者。然后将9传到cout,输出到屏幕。

输出:

9

 

看一下函数的其他调用:

   1: //#include <stdafx.h> // Visual Studio users need to uncomment this line
   2: #include <iostream>
   3:  
   4: int add(int x, int y)
   5: {
   6:     return x + y;
   7: }
   8:  
   9: int multiply(int z, int w)
  10: {
  11:     return z * w;
  12: }
  13:  
  14: int main()
  15: {
  16:     using namespace std;
  17:     cout << add(4, 5) << endl; // evalutes 4 + 5
  18:     cout << add(3, 6) << endl; // evalues 3 + 6
  19:     cout << add(1, 8) << endl; // evalues 1 + 8
  20:  
  21:     int a = 3;
  22:     int b = 5;
  23:     cout << add(a, b) << endl; // evaluates 3 + 5
  24:  
  25:     cout << add(1, multiply(2, 3)) << endl; // evalues 1 + (2 * 3)
  26:     cout << add(1, add(2, 3)) << endl; // evalues 1 + (2 + 3)
  27:     return 0;
  28: }

 

输出:

9
9
9
8
7
6

 

前三个调用是直接的。

地四处调用也是相对简单的:

   1: int a = 3;
   2: int b = 5;
   3: cout << add(a, b) << endl; // evaluates 3 + 5

 

在这个例子中,add调用,x=a,y=b。因为a = 3,b = 5,add(a,b)=add(3,5),它的结果为8.

让我们看一下第一个有点技巧性的语句:

   1: cout << add(1, multiply(2, 3)) << endl; // evalues 1 + (2 * 3)

 

当CPU试着调用函数add时,x = 1, y = multiply(2,3)。y不是一个整数,是一个函数调用。因此在CPU调用add函数之前,先调用multiply(),其中z = 2,w = 3。multiply(2,3)的值为6,讲这个值赋值给y。因此x = 1,y = 6,add(1,6)被调用,产生7。将7传给cout。

或用简单的方式表示(用=>符号表示求值):

add(1, multiply(2,3))=>add(1,6)=>7

下面语句中add函数的一个参数调用了add函数:

   1: cout << add(1, add(2, 3)) << endl; // evalues 1 + (2 + 3)

 

但是这个语句的执行与上述一致。

简单表示:

add(1,add(2,3))=>add(1,5)=>6

 

有效地使用函数

对于新手遇到的一个艰巨的问题(处理语言上的)是了解什么时候或怎样有效的使用一个函数。通过函数能够是你的程序分解为易管理的、易重复调用的部分,它们能够很容易的组合在一起实现更大的更复杂的功能。把你的程序分解成小的部分,程序整体的复杂性将会减少,这使得程序变得更加容易编写和修改。

 

当你学习C++的时候,你会写很多包含3个基本功能的程序:

  1. 读取用户输入的数据

  2. 从输入的值中计算结果

  3. 打印出计算值

对于简单的程序,用户输入数据的读取一般在main()函数中完成。但是,步骤2是函数重要的部分。函数将用户输入的作为参数,返回计算得到的结果。计算得到的结果能够打印出(直接在main()函数中,或是当计算结果很复杂、有特殊打印需求是,可以通过其他函数打印)。

 

一个好的规则是每个函数完成一项(仅一项)功能。新的程序员常常将第2步和第3步结合到一起。但是,计算数值结果和打印是两种不同的任务,这违背了仅实现一项功能的建议。理想上,一个函数计算结果,并返回,让调用者决定如何处理这个返回值。

posted @ 2012-04-16 10:12  grassofsky  阅读(366)  评论(0编辑  收藏  举报