第四节 · 分身术 · 函数重载

在日常生活中,"打开"这个词可以用在很多场景:打开门、打开书、打开电脑、打开网页……虽然都叫"打开",但具体的操作却完全不同。

C++ 中也有类似的机制,允许我们用同一个名字定义多个函数,只要它们的参数不同。这就是函数重载(Function Overloading)。


假设我们要编写一个函数来计算两个数的最大值。对于整数和浮点数,我们需要分别处理:

不使用重载的写法:

int maxInt(int a, int b)
{
    return (a > b) ? a : b;
}

double maxDouble(double a, double b)
{
    return (a > b) ? a : b;
}

使用函数重载:

int max(int a, int b)
{
    return (a > b) ? a : b;
}

double max(double a, double b)
{
    return (a > b) ? a : b;
}

现在,我们可以用同一个函数名 max 来处理不同类型的参数:

编译器会根据传入参数的类型,自动选择调用哪个版本的函数。这个过程称为重载决议(Overload Resolution)。


重载的规则

函数重载的依据是函数签名的不同。函数签名包括函数名和参数列表(参数的类型、个数和顺序),但不包括返回类型

以下情况可以构成重载:

以下情况不能构成重载:


重载与默认参数

当函数重载与默认参数结合使用时,需要注意避免二义性:

当调用 func(5) 时,它既可以匹配 func(int a),也可以匹配 func(int a, int b = 10)(使用默认参数)。编译器无法判断应该调用哪一个,因此会报错。


重载决议的过程

当编译器遇到函数调用时,它会按照以下步骤选择最佳匹配:

  1. 精确匹配:参数类型完全相同。

  2. 类型提升:如 charintfloatdouble

  3. 标准转换:如 intdouble,指针到 void*

  4. 用户定义的转换:使用转换函数或转换构造函数。

如果编译器找不到唯一的最佳匹配,就会报错,提示调用有二义性。


const 重载

对于引用和指针参数,const 和非 const 版本可以构成重载:

这种技术常用于实现容器的元素访问:对于非 const 对象返回可修改的引用,对于 const 对象返回只读引用。


成员函数的重载

类的成员函数也可以重载,而且 const 成员函数和非 const 成员函数可以构成重载:


运算符重载

函数重载的一个重要应用是运算符重载。我们可以为自定义类型重新定义运算符的行为:

运算符重载让我们能够以自然的方式操作自定义类型。我们将在后续章节中详细学习运算符重载。


函数重载是 C++ 的强大特性之一,它让我们能够用统一的接口处理不同类型的数据,使代码更加简洁易读。

习题

  • 编写一个名为 print 的重载函数系列,分别处理 intdoublestringint 数组的输出。

  • 为一个表示复数的结构体重载 +- 运算符。

Last updated