差别
这里会显示出您选择的修订版和当前版本之间的差别。
| 后一修订版 | 前一修订版 | ||
| cplus:函数 [2025/11/28 12:37] – 创建 张叶安 | cplus:函数 [2025/11/28 13:09] (当前版本) – 张叶安 | ||
|---|---|---|---|
| 行 1: | 行 1: | ||
| - | ====== | + | ====== 函数 (Functions) ====== |
| - | ===== 6.1 概述 ===== | + | ===== 概述 ===== |
| **作用**:将一段经常使用的代码封装起来,**减少重复代码**。 | **作用**:将一段经常使用的代码封装起来,**减少重复代码**。 | ||
| 行 7: | 行 7: | ||
| 一个较大的程序,一般分为若干个程序块,每个模块实现特定的功能。 | 一个较大的程序,一般分为若干个程序块,每个模块实现特定的功能。 | ||
| - | ===== 6.2 函数的定义 ===== | + | ===== 函数的定义 ===== |
| 函数的定义一般主要有5个步骤: | 函数的定义一般主要有5个步骤: | ||
| - | - 1、返回值类型 | + | - 返回值类型 |
| - | - 2、函数名 | + | - 函数名 |
| - | - 3、参数列表 | + | - 参数列表 |
| - | - 4、函数体语句 | + | - 函数体语句 |
| - | - 5、return 表达式 | + | - return 表达式 |
| **语法**: | **语法**: | ||
| 行 27: | 行 27: | ||
| </ | </ | ||
| - | * | + | |
| - | * | + | * |
| - | * | + | * |
| - | * | + | * |
| - | * | + | * |
| **示例**:定义一个加法函数,实现两个数相加。 | **示例**:定义一个加法函数,实现两个数相加。 | ||
| 行 44: | 行 44: | ||
| </ | </ | ||
| - | ===== 6.3 函数的调用 ===== | + | ===== 函数的调用 ===== |
| **功能**:使用定义好的函数。 | **功能**:使用定义好的函数。 | ||
| 行 83: | 行 83: | ||
| > **总结**:函数定义里小括号内称为形参,函数调用时传入的参数称为实参。 | > **总结**:函数定义里小括号内称为形参,函数调用时传入的参数称为实参。 | ||
| - | ===== 6.4 值传递 ===== | + | ===== 值传递 ===== |
| - | * | + | |
| - | * | + | * |
| **示例**: | **示例**: | ||
| 行 126: | 行 126: | ||
| > **解释**:在 `swap` 函数内部,`num1` 和 `num2` 确实交换了值,但这只是形参的改变。`main` 函数中的实参 `a` 和 `b` 的值并没有发生改变,这就是值传递的特性。 | > **解释**:在 `swap` 函数内部,`num1` 和 `num2` 确实交换了值,但这只是形参的改变。`main` 函数中的实参 `a` 和 `b` 的值并没有发生改变,这就是值传递的特性。 | ||
| - | ===== 6.5 函数的常见样式 ===== | + | ===== 函数的常见样式 ===== |
| 常见的函数样式有4种: | 常见的函数样式有4种: | ||
| - | - 1. 无参无返 | + | - 无参无返 |
| - | - 2. 有参无返 | + | - 有参无返 |
| - | - 3. 无参有返 | + | - 无参有返 |
| - | - 4. 有参有返 | + | - 有参有返 |
| **示例**: | **示例**: | ||
| 行 170: | 行 170: | ||
| </ | </ | ||
| - | ===== 6.6 函数的声明 ===== | + | ===== 函数的声明 ===== |
| **作用**:告诉编译器函数名称及如何调用函数。函数的实际主体可以单独定义。 | **作用**:告诉编译器函数名称及如何调用函数。函数的实际主体可以单独定义。 | ||
| - | * | + | |
| **示例**: | **示例**: | ||
| 行 205: | 行 205: | ||
| > **注意**:如果函数定义在 `main` 函数之后,必须在 `main` 函数之前写函数声明,否则编译器找不到该函数。 | > **注意**:如果函数定义在 `main` 函数之后,必须在 `main` 函数之前写函数声明,否则编译器找不到该函数。 | ||
| - | ===== 6.7 函数的分文件编写 ===== | + | ===== 函数的分文件编写 ===== |
| **作用**:让代码结构更加清晰。 | **作用**:让代码结构更加清晰。 | ||
| 行 211: | 行 211: | ||
| 函数分文件编写一般有4个步骤: | 函数分文件编写一般有4个步骤: | ||
| - | - 1. 创建后缀名为 `.h` 的头文件 | + | - 创建后缀名为 `.h` 的头文件 |
| - | - 2. 创建后缀名为 `.cpp` 的源文件 | + | - 创建后缀名为 `.cpp` 的源文件 |
| - | - 3. 在头文件中写函数的声明 | + | - 在头文件中写函数的声明 |
| - | - 4. 在源文件中写函数的定义 | + | - 在源文件中写函数的定义 |
| **示例**: | **示例**: | ||
| 行 254: | 行 254: | ||
| int b = 200; | int b = 200; | ||
| swap(a, b); | swap(a, b); | ||
| + | |||
| + | system(" | ||
| + | |||
| + | return 0; | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | ===== 函数提高 ===== | ||
| + | |||
| + | ==== 函数默认参数 ==== | ||
| + | |||
| + | 在C++中,函数的形参列表中的形参是可以有默认值的。 | ||
| + | |||
| + | **语法**:< | ||
| + | |||
| + | **示例代码:** | ||
| + | |||
| + | <code cpp> | ||
| + | #include < | ||
| + | using namespace std; | ||
| + | |||
| + | // 函数默认参数 | ||
| + | // 如果我们自己传入数据,就用自己的数据,如果没有,那么就用默认值 | ||
| + | // 语法: 返回值类型 函数名 (形参 = 默认值) {} | ||
| + | int func(int a, int b = 10, int c = 10) { | ||
| + | return a + b + c; | ||
| + | } | ||
| + | |||
| + | // 注意事项: | ||
| + | // 1. 如果某个位置参数有默认值,那么从这个位置往后,从左向右,必须都要有默认值 | ||
| + | // int func2(int a = 10, int b = 10, int c) { // 错误,c没有默认值 | ||
| + | // return a + b + c; | ||
| + | // } | ||
| + | |||
| + | // 2. 如果函数声明有默认值,函数实现的时候就不能有默认参数 | ||
| + | // 声明和实现只能有一个有默认参数 | ||
| + | int func2(int a = 10, int b = 10); | ||
| + | |||
| + | int func2(int a, int b) { | ||
| + | return a + b; | ||
| + | } | ||
| + | |||
| + | int main() { | ||
| + | |||
| + | cout << "ret = " << func(20, 20) << endl; // 传入两个参数,c使用默认值 | ||
| + | cout << "ret = " << func(100) << endl; // 传入一个参数,b和c使用默认值 | ||
| + | |||
| + | system(" | ||
| + | |||
| + | return 0; | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | ==== 函数占位参数 ==== | ||
| + | |||
| + | C++中函数的形参列表里可以有占位参数,用来做占位,调用函数时必须填补该位置。 | ||
| + | |||
| + | **语法**:< | ||
| + | |||
| + | 在现阶段函数的占位参数存在意义不大,但是后面的课程中会用到该技术(如重载前置和后置递增运算符)。 | ||
| + | |||
| + | **示例代码:** | ||
| + | |||
| + | <code cpp> | ||
| + | #include < | ||
| + | using namespace std; | ||
| + | |||
| + | // 函数占位参数,占位参数也可以有默认参数 | ||
| + | void func(int a, int = 10) { | ||
| + | cout << "this is func" << endl; | ||
| + | } | ||
| + | |||
| + | int main() { | ||
| + | |||
| + | // func(10, 10); // 占位参数必须填补 | ||
| + | func(10); // 如果占位参数有默认值,可以不填补 | ||
| + | |||
| + | system(" | ||
| + | |||
| + | return 0; | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | ==== 函数重载 ==== | ||
| + | |||
| + | === 函数重载概述 === | ||
| + | |||
| + | **作用**:函数名可以相同,提高复用性。 | ||
| + | |||
| + | **函数重载满足条件**: | ||
| + | * | ||
| + | * | ||
| + | * | ||
| + | |||
| + | **注意**:函数的返回值不可以作为函数重载的条件。 | ||
| + | |||
| + | **示例代码:** | ||
| + | |||
| + | <code cpp> | ||
| + | #include < | ||
| + | using namespace std; | ||
| + | |||
| + | // 函数重载需要函数都在同一个作用域下 | ||
| + | void func() | ||
| + | { | ||
| + | cout << "func 的调用!" | ||
| + | } | ||
| + | |||
| + | void func(int a) | ||
| + | { | ||
| + | cout << "func (int a) 的调用!" | ||
| + | } | ||
| + | |||
| + | void func(double a) | ||
| + | { | ||
| + | cout << "func (double a)的调用!" | ||
| + | } | ||
| + | |||
| + | void func(int a, double b) | ||
| + | { | ||
| + | cout << "func (int a ,double b) 的调用!" | ||
| + | } | ||
| + | |||
| + | void func(double a, int b) | ||
| + | { | ||
| + | cout << "func (double a ,int b)的调用!" | ||
| + | } | ||
| + | |||
| + | // 函数返回值不可以作为函数重载条件 | ||
| + | // int func(double a, int b) | ||
| + | // { | ||
| + | // cout << "func (double a ,int b)的调用!" | ||
| + | // } | ||
| + | |||
| + | int main() { | ||
| + | |||
| + | func(); | ||
| + | func(10); | ||
| + | func(3.14); | ||
| + | func(10, 3.14); | ||
| + | func(3.14, 10); | ||
| + | |||
| + | system(" | ||
| + | |||
| + | return 0; | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | === 函数重载注意事项 === | ||
| + | |||
| + | * | ||
| + | * | ||
| + | |||
| + | **示例代码:** | ||
| + | |||
| + | <code cpp> | ||
| + | #include < | ||
| + | using namespace std; | ||
| + | |||
| + | // 函数重载注意事项 | ||
| + | // 1、引用作为重载条件 | ||
| + | |||
| + | void func(int &a) // int &a = 10; 不合法 | ||
| + | { | ||
| + | cout << "func (int &a) 调用 " << endl; | ||
| + | } | ||
| + | |||
| + | void func(const int &a) // const int &a = 10; 合法 | ||
| + | { | ||
| + | cout << "func (const int &a) 调用 " << endl; | ||
| + | } | ||
| + | |||
| + | // 2、函数重载碰到函数默认参数 | ||
| + | |||
| + | void func2(int a, int b = 10) | ||
| + | { | ||
| + | cout << " | ||
| + | } | ||
| + | |||
| + | void func2(int a) | ||
| + | { | ||
| + | cout << " | ||
| + | } | ||
| + | |||
| + | int main() { | ||
| + | |||
| + | int a = 10; | ||
| + | func(a); // 调用无const,因为a是变量,可读可写 | ||
| + | func(10);// | ||
| + | |||
| + | // func2(10); // 碰到默认参数产生歧义,需要避免 | ||
| + | // 编译器不知道是调用带默认参数的func2,还是只带一个int参数的func2 | ||
| system(" | system(" | ||