函数的默认参数与重载

这节课,我们来学习 C++ 中函数对 C 语言函数的两个扩展:默认参数重载

默认参数

在 C++ 中,默认参数是在函数定义时给参数指定一个默认值,这样当调用函数时,如果没有为该参数提供具体的值,则会自动使用这个默认值。默认参数使得函数调用更加灵活和方便。

在函数定义时,可以在参数列表中直接为参数指定一个默认值。例如:

#include <iostream>
using namespace std;

void func(int var_int, char var_char = 'B', float var_float = 3.14) {
    cout << "var_int: " << var_int << ", var_char: " << var_char << ", var_float: " << var_float << endl;
}

int main() {
    int a = 250;
    char b = 'V';
    float c = 66.66;

    // 填写所有参数,不使用默认参数
    func(a, b, c);
    // 使用默认参数
    func(a, b);
    func(a);

    return 0;
}

以上代码 func 函数中的 var_char 与 var_float 都是默认参数,所以我们在调用 func 函数的时候就可以省略对应的实参。

C++ 规定,默认参数只能放在形参列表的最后,而且一旦为某个形参指定了默认值,那么它后面的所有形参都必须有默认值。实参和形参的传值是从左到右依次匹配的,默认参数的连续性是保证正确传参的前提。

下面的写法是正确的:

void func(int a, int b = 10, int c = 20);
void func(int a, int b, int c = 20);

但这样写不可以:

void func(int a, int b = 10, int c = 20, int d)
void func(int a, int b = 10, int c, int d = 20);

最后需要注意的一点是,函数声明‌(通常在头文件中)需要被其他调用代码可见,因此默认值必须在声明时指定。若在定义中指定默认值,而调用代码未包含该定义,会导致编译错误。

#include <iostream>
using namespace std;

void func(int var_int, char var_char = 'B', float var_float = 3.14);

int main() {
    int a = 250;
    char b = 'V';
    float c = 66.66;

    // 填写所有参数,不使用默认参数
    func(a, b, c);
    // 使用默认参数
    func(a, b);
    func(a);

    return 0;
}

void func(int var_int, char var_char, float var_float) {
    cout << "var_int: " << var_int << ", var_char: " << var_char << ", var_float: " << var_float << endl;
}

函数重载 - Function Overloading

接着,我们再来看一个 C++ 对 C 语言的补充内容 - 函数重载

C++ 中的 函数重载(Function Overloading) 是一种允许在同一作用域内定义多个同名函数,但这些函数的参数列表(参数个数、类型或顺序)不同的特性。编译器会根据函数调用时传递的参数类型和数量来决定调用哪一个版本的函数。

构成函数重载需要以下条件:

  1. 函数名相同:重载的函数必须具有相同的函数名。
  2. 参数列表不同:重载的函数的参数列表必须不同。这包括参数的类型、个数或顺序不同。
    • 参数类型不同:例如,一个函数接受 int 类型参数,另一个函数接受 double 类型参数。
    • 参数个数不同:例如,一个函数没有参数,另一个函数有一个或多个参数。
    • 参数顺序不同:例如,一个函数接受 int 和 double 类型的参数,但顺序为 (int, double),另一个函数也接受 int 和 double 类型的参数,但顺序为 (double, int)

提示

函数的返回类型不同并不构成函数重载的条件。编译器无法通过返回值类型来确定调用哪个重载函数。

函数重载的作用:

  1. 提高代码的可读性和可维护性:通过函数重载,可以为不同的操作或数据类型提供统一的接口,使得函数的使用更加灵活和方便。
  2. 避免命名上的冗余:函数重载使得程序员可以定义多个功能相似但处理不同数据类型的函数,而无需为它们起不同的名字。

以下是函数重载的示例:

  1. 函数形参个数不同

    int add(int x, int y)
    {
        return x + y;
    }
    
    int add(int x, int y, int z)
    {
        return x + y + z;
    }
    
  2. 函数形参类型不同

    int add(int x, int y)
    {
        return x + y;
    }
    
    double add(double x, double y)
    {
        return x + y;
    }
  3. 函数形参顺序不同

    double add(int x, double y)
    {
        return x + y;
    }
    
    double add(double x, int y)
    {
        return x + y;
    }
    

注意:下面这种不算形参顺序不同

int add(int x, int y)
{
    return x + y;
}

int add(int y, int x)
{
    return x + y;
}

这两种函数本质上算是同一个函数。