章节目录

函数重载简介

本节阅读量:

考虑以下函数:

1
2
3
4
int add(int x, int y)
{
    return x + y;
}

这个简单的函数会将两个整数相加,并返回一个整数结果。然而,如果我们还需要一个可以将两个浮点数相加的函数,该怎么办?这个add()函数并不适用,因为任何浮点参数都会被转换为整数,从而导致浮点参数丢失小数部分。

解决此问题的一种方法是使用稍微不同的名称定义多个函数:

1
2
3
4
5
6
7
8
9
int addInteger(int x, int y)
{
    return x + y;
}

double addDouble(double x, double y)
{
    return x + y;
}

然而,为了获得较好的效果,我们需要为具有不同参数类型的类似函数制定一致的命名标准,记住这些函数名,并在实际调用时选择正确的函数。

那么,当我们需要一个类似的函数,将3个整数而不是2个整数相加时,又该怎么办?为每个函数管理唯一名称很快就会变得繁琐。


函数重载简介

幸运的是,C++有一个优雅的解决方案来处理这种情况。函数重载允许我们创建多个同名函数,只要每个同名函数具有不同的参数类型(或者可以通过其他方式区分)。每个共享名称(在同一作用域内)的函数都被称为重载函数(有时简称为重载)。

要重载我们的add()函数,我们只需声明另一个接收double参数的add()函数:

1
2
3
4
double add(double x, double y)
{
    return x + y;
}

现在,在同一作用域内有两个版本的add():

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
int add(int x, int y) // 整数版本
{
    return x + y;
}

double add(double x, double y) // 浮点数版本
{
    return x + y;
}

int main()
{
    return 0;
}

上述程序可以编译。尽管您可能认为这些函数会导致命名冲突,但这里并不会。由于这些函数的参数类型不同,编译器能够区分它们,并将它们视为碰巧共享名称的独立函数。


重载决议

当对已重载的函数进行函数调用时,编译器会基于函数调用中使用的参数,尝试将该调用与合适的重载函数相匹配。这称为重载决议。

下面是一个简单的示例来演示这一点:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>

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

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

int main()
{
    std::cout << add(1, 2); // 调用 add(int, int)
    std::cout << '\n';
    std::cout << add(1.2, 3.4); // 调用 add(double, double)

    return 0;
}

上述程序编译并产生结果:

1
2
3
4.6

当我们在add(1, 2)的调用中提供整数参数时,编译器将确定我们正在尝试调用add(int, int)。当我们在add(1.2, 3.4)的调用中提供浮点参数时,编译器将确定我们正在尝试调用add(double, double)。


使其可编译

为了编译使用重载函数的程序,必须满足两个条件:

  1. 每个被重载的函数都必须与其他重载函数不同。
  2. 每个实际的函数调用都必须能解析到一个对应的重载函数。

如果重载函数无法互相区分,或者函数调用无法解析到对应的重载函数,则将导致编译错误。

在下一课中,我们将探索重载函数之间如何互相区分。再下一课中,我们将探索编译器如何将函数调用解析到对应的重载函数。


结论

函数重载可以减少需要记住的函数名数量,是降低程序复杂性的一种好方法。它可以而且应该自由使用。


10.9 第10章总结

上一节

11.1 被重载函数之间互相区分

下一节