自定义函数
1.什么是函数
在数学中,函数是一种基本的数学对象,它建立了一个集合(称为定义域)中的每个元素与另一个集合(称为值域)中的唯一元素之间的对应关系。简单地说,函数就是一个规则,它接收一个或多个输入值(也称为自变量),并据此产生一个确定的输出值(称为函数值或因变量)。举个例子,我们去超市买苹果,苹果的价格是5元/千克。那么无论你买的苹果重量是多少,都会对应一个相应的价格。这里苹果的重量(自变量)与苹果的价格(因变量)之间就有一个对应规则(函数):价格=5元/千克 *重量。如果超市规定苹果每人限购10公斤,那么苹果的重量只能是0~10之间的值。这个[0,10]就是这个函数的定义域,[0-50]就是这个函数的值域。
在数学上的函数通常用 f 表示,并写作 : y = f(x),这里的 x 是自变量, y是相应于x的函数值。例如,f(x) = 5 * x + 0.5 就是一个关于苹果价格的函数,其中x是重量,0.5 是包装袋的钱。
2.C++中的自定义函数
在C++中,函数的概念与数学中的类似,但更加强大。自定义函数是一种非常强大的工具,它允许你将代码块封装起来,以便在程序的不同部分重复使用。自定义函数有助于提高代码的可读性、可维护性和重用性。使用自定义函数一般分声明函数原型、定义函数以及函数调用三个过程。
(1)声明函数原型:
声明函数原型(Function Prototype)是一个非常重要的步骤,它告诉编译器有关函数的名称、返回类型和参数列表的信息。函数原型通常放在程序的开始部分,或者放在头文件中,以便在多个源文件中使用。函数原型的语法:
返回类型 函数名(参数列表);
例如:
(2)定义函数
一个函数通常包括以下几个部分:
返回类型:函数返回的数据类型(例如 int, float, void 等)。
函数名:函数的名称,用于调用函数。
参数列表:函数接受的输入值(参数)。
函数体:包含实际代码的块,用大括号 {} 包围。
函数的结构如下:
返回类型 函数名(参数列表) {
// 函数体
// 执行代码
return 返回值; // 如果有返回类型
}
例1.简单的无参数函数体
void sayHello()
{
cout << “Hello, World!” << endl;
}
例2.带参数的函数体
void greet(string name)
{
cout << “Hello, ” << name << “!” << endl;
}
例3.带返回值的函数体
int add(int a, int b)
{
int sum = a + b;
return sum; // 返回值
}
(3)调用函数
调用函数(Function Call)是指在程序的某个位置使用函数名并提供必要的参数来执行函数定义中的代码。调用函数的语法:
函数名(参数列表);
变量 = 函数名(参数列表);
注意事项:
局部变量:函数体内部可以声明局部变量,这些变量只在函数体内有效。
return 语句:如果函数有返回类型,函数体必须包含一个 return 语句来返回一个值。
执行流程:函数体中的代码按照从上到下的顺序执行,除非遇到控制流语句(如 if、for、while 等)。
参数匹配:调用函数时提供的参数必须与函数定义中的参数类型和数量匹配。
返回值处理:如果函数有返回值,调用函数时通常需要将返回值存储在变量中或直接使用。
函数调用顺序:函数可以在其他函数内部调用,但必须确保在调用之前已经声明或定义了该函数。
3.形参与实参
在函数定义和调用过程中,我们经常会涉及到“形参”和“实参”这两个概念。它们是函数参数的两种不同表现形式,分别在函数定义和函数调用时使用。
(1)形参(Formal Parameters)
形参是函数定义时列出的参数。它们是函数内部的局部变量,用于接收调用函数时传递的值。形参的作用范围仅限于函数内部,函数外部无法访问。
例如,在下面的函数定义中,a 和 b 是形参:
void add(int a, int b)
{
int sum = a + b;
// 使用形参 a 和 b 进行计算
}
(2)实参(Actual Parameters)
实参是函数调用时传递给函数的具体值或变量。实参的值会被复制到对应的形参中,从而在函数内部使用。
例如,在下面的函数调用中,x 和 y 是实参:
int x = 5;
int y = 3;
add(x, y);
(3)形参与实参的关系
当函数被调用时,实参的值会被传递给形参。这个过程可以是值传递、地址传递或引用传递,具体取决于函数定义时形参的类型。以下是一个简单的示例,展示了形参和实参的使用:
#include <bits/stdc++.h>
using namespace std;
// 函数定义,a 和 b 是形参
void swap(int a, int b)
{
int temp = a;
a = b;
b = temp;
cout << "Inside swap: a = " << a << ", b = " << b << endl;
}
int main()
{
int x = 5;
int y = 10;
// 函数调用,x 和 y 是实参
swap(x, y);
cout << "Outside swap: x = " << x << ", y = " << y << endl;
return 0;
}
输出结果:
Inside swap: a = 10, b = 5
Outside swap: x = 5, y = 10
在这个示例中,swap 函数的形参 a 和 b 接收了实参 x 和 y 的值。由于是值传递,函数内部对 a 和 b 的修改不会影响到外部的 x 和 y。
总结
形参:函数定义时列出的参数,用于接收调用时传递的值。
实参:函数调用时传递给函数的具体值或变量。
当函数被调用时,实参的值会被传递给形参。这个过程可以是值传递、地址传递或引用传递,具体取决于函数定义时形参的类型。
4.函数参数的传递
在C++中,函数参数可以通过不同的方式传递,主要包括值传递、地址传递和引用传递。每种方式都有其特定的用途和效果。
(1)值传递(Pass by Value)
在值传递中,函数参数是实际参数的副本。这意味着函数内部对参数的任何修改都不会影响到实际参数。例如下面代码:
#include <bits/stdc++.h>
using namespace std;
void increment(int x)
{
x++;
cout << "Inside function: " << x << endl;
}
int main()
{
int a = 5;
increment(a);
cout << "Outside function: " << a << endl;
return 0;
}
输出的结果是:
Inside function: 6
Outside function: 5
虽然在increment()函数中对变量的值进行修改(x++),但是不会影响主函数中变量的值。
(2)地址传递(Pass by Pointer)
在地址传递中,函数参数是指向实际参数的指针。这意味着函数内部可以通过指针修改实际参数的值。例如下面的代码:
#include <bits/stdc++.h>
using namespace std;
void increment(int *x)
{
(*x)++;
cout << "Inside function: " << *x << endl;
}
int main()
{
int a = 5;
increment(&a);
cout << "Outside function: " << a << endl;
return 0;
}
输出结果为:
Inside function: 6
Outside function: 6
通过示例可以看到,在increment()函数中,通过指针修改了主函数变量的值。因为函数传递的是地址,所以在increment()函数中和主函数中修改的是同一个变量。
(3)引用传递(Pass by Reference)
在引用传递中,函数参数是实际参数的引用。这意味着函数内部对参数的任何修改都会直接影响到实际参数。示例代码如下:
#include <bits/stdc++.h>
using namespace std;
void increment(int &x)
{
x++;
cout << "Inside function: " << x << endl;
}
int main()
{
int a = 5;
increment(a);
cout << "Outside function: " << a << endl;
return 0;
}
输出结果为:
Inside function: 6
Outside function: 6
值传递:函数内部对参数的修改不会影响到实际参数。
地址传递:函数内部可以通过指针修改实际参数的值。
引用传递:函数内部对参数的修改会直接影响到实际参数,且语法上更简洁。
选择哪种传递方式取决于具体的需求和设计。例如,如果需要在函数内部修改实际参数的值,通常会选择地址传递或引用传递。如果不需要修改实际参数的值,值传递是一个安全的选择。
