函数

函数是一组一起执行一个任务的语句。每个 C++ 程序都至少有一个函数,即主函数 main() ,所有简单的程序都可以定义其他额外的函数。

在 C++ 中,使用函数有很多优点,其中包括:

您可以重用函数中的代码,一旦一个函数被写入,它可以在程序中调用多次。
您可以轻松地测试各个函数。
如果需要修改代码,可以在一个函数中进行修改,而不必改变程序结构。
您可以对不同的输入使用相同的函数。

返回类型

一个函数可以返回一个值。函数的返回类型在其名称前面声明。

下面是个例子,main 函数一般有以下形式:

int main()
{
  // 其余代码
  return 0;
}

在上面的例子中,返回类型是int,它表示函数返回一个整数值。

提示:有些函数执行所需的操作而不返回值,这些函数是用关键字 void 定义的。

定义函数

C++ 中的函数定义的一般形式如下:

return_type function_name( parameter list )
{
   body of the function
}

在 C++ 中,函数由一个函数头和一个函数主体组成。下面列出一个函数的所有组成部分:
返回类型:一个函数可以返回一个值。return_type 是函数返回的值的数据类型。有些函数执行所需的操作而不返回值,在这种情况下,return_type 是关键字 void。
函数名称:这是函数的实际名称。函数名和参数列表一起构成了函数签名。
参数:参数就像是占位符。当函数被调用时,您向参数传递一个值,这个值被称为实际参数。参数列表包括函数参数的类型、顺序、数量。参数是可选的,也就是说,函数可能不包含参数。
函数主体:函数主体包含一组定义函数执行任务的语句。
在 C++ 中,要调用一个函数,只需要将所需的参数和函数名称一起传递。

函数调用

让我们定义一个函数,它不返回值,只需在屏幕上打印一行文本。

void doSomething() 
{
  cout << "Hello edong!";
}

doSomething()函数返回void,并且没有参数。

现在,我们可以在main() 中使用我们的函数。

int main() 
{
   doSomething();

   return 0;
}
#include <iostream>
using namespace std;

void doSomething() {
  cout << "Hello edong!";
}

int main() {
  doSomething();

  return 0;
}

提示:如果将声明放在main() 函数后面会导致错误。

函数声明

函数声明会告诉编译器函数名称及如何调用函数。函数的实际主体可以单独定义。

下面是一个例子:

#include <iostream>
using namespace std;

// 函数声明
void doSomething();

int main() {
  doSomething();

  return 0;
}

// 函数定义
void doSomething() {
  cout << "Hello edong!";
}

提示:当您在一个源文件中定义函数且在另一个文件中调用函数时,函数声明是必需的。在这种情况下,您应该在调用函数的文件顶部声明函数。

函数参数

如果函数要使用参数,则必须声明接受参数值的变量。这些变量称为函数的形式参数。

形式参数就像函数内的其他局部变量,在进入函数时被创建,退出函数时被销毁。

下面是一个例子:

void doSomething(int x) 
{
   cout << x;
}

在上面的例子,定义了一个函数,它接受一个整型参数并打印它的值。
一旦定义了参数,就可以在函数被调用时传递相应的参数。

下面是一个例子:

#include <iostream>
using namespace std;

void doSomething(int x) {
  cout << x;
}

int main() {
  doSomething(30);
}

// 输出 30

值30作为参数传递给函数,并赋值给函数的形式参数:x。

提示:在这种情况下,修改函数内的形式参数对实际参数没有影响。
您可以将不同的参数传递给相同的函数。

下面是一个例子:

int w3cTest(int x) {
   return x*2;
}

在例子中,定义了一个整型参数的函数,并返回其值,乘以2。

现在,我们可以用不同的参数来使用这个函数。

int main() {
  cout << w3cTest(2);
  // 输出 4

  cout << w3cTest(3);
  // 输出 6

  cout << w3cTest(4);
  // 输出 8
}

定义多个参数

在 C++ 中,您可以根据需要为函数定义多个参数,并用逗号分隔它们。

下面是一个例子,让我们创建一个返回两个参数之和的函数。

int sum(int num1, int num2) {
 // 其余代码
}

在例子中,sum函数接受两个int类型的参数,并返回int。

现在,让我们计算两个参数的总和并返回结果:

int sum(int num1, int num2) {
  int result = num1 + num2;
  return result;
}

现在,我们可以调用这个函数。

int sum(int num1, int num2) {
  int result = num1 + num2;
  return result;
}

int main() {
  cout << sum(17, 33);
  // 输出 50
}

您也可以将返回的值赋值给一个变量。

int main() {
  int num1 = sum(7, 28);
  cout << num1;
  // 输出 35
}

在 C++ 中,您可以将任意数量的参数添加到一个函数中。

下面是一个例子:

int sum(int num1, int num2, int num3) {
  int result = num1 + num2 + num3;
  return result;
}

提示:请记住,用逗号分隔多个参数。

rand() 函数

rand() 函数
能够生成随机数在很多情况下都很有用,包括创建游戏,统计建模程序和类似的最终产品。

在C++ 标准库中,可以访问被称为rand()的伪随机数生成器函数。在使用时,我们需要包含头文件。

下面是一个示例:

#include <iostream>
#include <cstdlib>
using namespace std;

int main() {
  cout << rand();
}

这将输出一个随机数。

模(%) 运算符生成随机数

在 C++ 中,可以使用模(%) 运算符来生成特定范围内的随机数。

下面是一个例子,生成1到5范围内的整数。

int main () {
  for (int x = 1; x <= 10; x++) {
  cout << 1 + (rand() % 5) << endl;
  }
}

/* 输出: 
2
3
5
1
5
5
4
4
3
5
*/

但是,rand() 函数只会返回一个伪随机数。这意味着每次运行代码时,都会生成相同的编号。

srand() 函数

在 C++ 中,srand() 函数用于生成真正的随机数(随机种子)。

srand() 函数允许指定一个种子(seed) 值作为其参数,用于rand() 函数的算法。

下面是一个例子:

int main () {
  srand(30);

  for (int x = 1; x <= 10; x++) {
    cout << 1 + (rand() % 5) << endl;
  }
}

更改种子(seed) 值会改变rand() 的返回值。但是,相同的参数将导致相同的输出。

生成真正的随机数

在 C++ 中,生成真正随机数的方法是使用当前时间作为srand() 函数的种子值。

下面是一个例子,用time() 函数来获得系统时间的秒数,并随机种子给rand() 函数。在使用时,我们需要包含ctime头文件。

#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

int main () {
  srand(time(0));

  for (int x = 1; x <= 10; x++) {
    cout << 1 + (rand() % 5) << endl;
  }
}

time(0) 将返回当前秒数,提示srand() 函数每次程序运行时为rand() 函数设置一个不同的种子。

提示:每次我们运行程序时,使用这个种子值将会创建一个不同的输出。

参数的默认值

当您定义一个函数,您可以为参数列表中后边的每一个参数指定默认值。当调用函数时,如果实际参数的值留空,则使用这个默认值。

这是通过在函数定义中使用赋值运算符来为参数赋值的。请看下面的实例:

int sum(int a, int b=17) {
  int result = a + b;
  return (result);
}

这为b参数赋值了一个默认值17,如果我们调用函数而不传递b参数的值,将使用默认值。

int main() {
  int x = 12;
  int y = 18;

  //用x和y两个参数调用函数
  int result = sum(x, y);
  cout << result << endl;
  //输出 30

  //不用b调用函数
  result = sum(x);
  cout <<  result << endl;
   //输出 29

  return 0;
}

在代码中,对函数的第二次调用不会传递第二个参数的值,而是使用默认值17。

函数重载

在同一个作用域内,可以声明几个功能类似的同名函数,但是这些同名函数的形式参数(指参数的个数、类型)必须不同。

例如,您可能需要一个w3cTest() 函数来打印其参数的值。

void w3cTest(int a) { 
  cout << a;
}

这只对整型参数有效。重载它将使其可用于其他类型,如浮点型。

void w3cTest(float a) { 
  cout << a;
}

现在,相同的w3cTest() 函数名称将适用于整数和浮点数。
当重载函数时,函数的定义必须根据参数列表中的参数的个数、或类型而不同。

下面是一个例子:

void w3cTest(int x) {
    cout << "整数为: " << x << endl;
}
void w3cTest(float x) {
    cout << "浮点数为: " << x << endl;
}
int main() {
  int a = 30;
  float b = 68.652;
  w3cTest(a);
  w3cTest(b);
}

/* 输出:  
整数为: 30
浮点数为: 68.652
*/

如你所见,函数调用是基于提供的参数。一个整数参数将调用带有整数参数的函数,一个浮点数参数将调用执行一个浮点数参数的函数。
您不能仅通过返回类型的不同来重载函数。

下面的声明将导致错误。

int w3cTest(int a) {}
float w3cTest(int b) {}
string w3cTest(int c) {}

虽然每个函数都使用相同的名称,但唯一的区别是返回类型,这是不允许的

递归

在C++中,递归函数是一个自我调用的函数。

为了避免递归无限地运行,您必须包含终止条件。

现在,为了演示递归,我们创建一个程序来计算一个数字的阶乘。
在数学中,阶乘阶数是指所有小于或等于特定的非负整数(n)的正整数的乘积。n的阶乘表示为n!。

例如:

5! = 5 * 4 * 3 * 2 * 1 = 120

现在,让我们来定义我们的函数:

int factorial(int n) {
  if (n==1) {
    return 1;
  }
  else {
    return n * factorial(n-1);
  }
}

if 语句定义退出条件。在这种情况下,当n等于1时,返回1(1的阶乘是1)。

我们将递归函数调用放在else语句中,返回n乘以n-1的阶乘。

例如,如果使用参数3调用阶乘函数,它将执行如下: 返回3 * factorial(2),即3 * 2 * factorial(1),即3 * 2 * 1。

提示:阶乘(factorial)函数自我调用,然后一直继续,直到参数等于1。

#include <iostream>
using namespace std;
int fact(int n) {

      if (n == 1) {
        return 1;
      }
      else {
      return n * fact(n-1);
      }
    }
int main()
{
    cout << fact(3);
}

退出条件的另一个名称是基本情况。

提示:一个退出条件(基本情况)是真正的递归所必需的。没有它,递归将永远持续运行。

将数组传递给函数

在 C++ 中,一个数组也可以作为参数传递给一个函数。

声明函数时,参数应该用方括号[] 来定义。

下面是一个例子:

void w3cArray(int arr[], int size) {
  for(int x=0; x<size; x++) {
    cout << arr[x];
  }
}

现在,我们可以在main() 中使用我们的函数,并在数组中调用它。

void w3cArray(int arr[], int size) {
  for(int x=0; x<size; x++) {
    cout << arr[x] << endl;
  }
}
int main() {
  int myArr[3]= {17, 30, 28};
  w3cArray(myArr, 3);
}

在代码中,w3cArray函数将数组作为参数(int arr[]),并使用for循环遍历数组。

我们在main() 中调用函数,这是我们将myArr数组传递给打印元素的函数的地方。

提示:请记住,要将数组作为参数传递给函数,请指定不带方括号的数组名称。

函数传递参数的方式

当调用函数时,有两种向函数传递参数的方式:

传值调用

传值调用:该方法把参数的实际值复制给函数的形式参数。在这种情况下,修改函数内的形式参数对实际参数没有影响。

引用调用:该方法把参数的引用复制给形式参数。在函数内,该引用用于访问调用中要用到的实际参数。这意味着,修改形式参数会影响实际参数。

提示:默认情况下,C++ 使用传值调用来传递参数。
默认情况下,C++ 使用传值调用方法来传递参数。一般来说,这意味着函数内的代码不会改变用于调用函数的实际参数。

下面是一个例子:

void swap(int x) {
  x = 50;
}

int main() {
  int var = 10;
  swap(var);
  cout << var;
}

// 输出 10

引用调用

向函数传递参数的引用调用方法,把引用的地址复制给形式参数。在函数内,该引用用于访问调用中要用到的实际参数。这意味着,修改形式参数会影响实际参数。

按引用传递值,参数引用被传递给函数,就像传递其他值给函数一样。

下面是一个例子:

void swap(int *x) {
  *x = 50;
}

int main() {
  int var = 10;
  swap(&var);
  cout << var;
}
// 输出 50

如你所见,我们使用操作符&的地址将变量直接传递给函数。

函数声明表示该函数将一个指针作为其参数(使用 * 运算符定义)。

结果,函数实际上已经改变了参数的值,通过指针访问它。
一般来说,传值调用更快,更有效。当函数需要修改参数时,或者当需要传递一个数据类型时,如果通过引用调用,这会占用大量的内存,而且复制的代价很高。

最后修改:2022 年 12 月 05 日
如果觉得我的文章对你有用,请随意赞赏