考虑以下函数
int add(int x, int y)
{
return x + y;
}
这个简单的函数将两个整数相加并返回一个整数结果。但是,如果我们也想要一个可以相加两个浮点数的函数呢?这个 add()
函数不适用,因为任何浮点参数都会被转换为整数,导致浮点参数失去其小数部分。
解决这个问题的一种方法是定义多个名称略有不同的函数
int addInteger(int x, int y)
{
return x + y;
}
double addDouble(double x, double y)
{
return x + y;
}
然而,为了达到最佳效果,这要求您为具有不同类型参数的类似函数定义一个一致的函数命名标准,记住这些函数的名称,并实际调用正确的函数。
那么,当我们想要一个类似的功能,但需要添加 3 个整数而不是 2 个时,会发生什么呢?为每个函数管理唯一的名称很快就会变得繁琐。
函数重载简介
幸运的是,C++ 有一个优雅的解决方案来处理这种情况。函数重载允许我们创建多个同名函数,只要每个同名函数具有不同的参数类型(或者函数可以通过其他方式区分)。共享名称(在相同作用域内)的每个函数都称为重载函数(有时简称为重载)。
要重载我们的 add()
函数,我们只需声明另一个接受 double 参数的 add()
函数
double add(double x, double y)
{
return x + y;
}
我们现在在同一个作用域中有两个版本的 add()
int add(int x, int y) // integer version
{
return x + y;
}
double add(double x, double y) // floating point version
{
return x + y;
}
int main()
{
return 0;
}
上面的程序将编译。尽管您可能期望这些函数会导致命名冲突,但这里不是这种情况。由于这些函数的参数类型不同,编译器能够区分这些函数,并将它们视为只是恰好共享一个名称的独立函数。
关键见解
只要每个重载函数都可以被编译器区分,函数就可以被重载。如果重载函数无法区分,则会导致编译错误。
相关内容
运算符也可以以类似的方式重载。我们将在 21.1 -- 运算符重载简介 中讨论运算符重载。
重载解析简介
此外,当调用已重载的函数时,编译器将尝试根据函数调用中使用的参数将函数调用与适当的重载进行匹配。这称为重载解析。
这是一个简单的示例,演示了这一点
#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); // calls add(int, int)
std::cout << '\n';
std::cout << add(1.2, 3.4); // calls add(double, double)
return 0;
}
上面的程序编译并产生结果
3 4.6
当我们在调用 add(1, 2)
中提供整数参数时,编译器将确定我们正在尝试调用 add(int, int)
。当我们在调用 add(1.2, 3.4)
中提供浮点参数时,编译器将确定我们正在尝试调用 add(double, double)
。
使其编译
为了使使用重载函数的程序编译,必须满足两个条件
- 每个重载函数都必须与其他函数区分开来。我们在课程 11.2 -- 函数重载区分 中讨论了如何区分函数。
- 对重载函数的每次调用都必须解析为重载函数。我们在课程 11.3 -- 函数重载解析和模糊匹配 中讨论了编译器如何将函数调用与重载函数进行匹配。
如果重载函数未区分,或者对重载函数的函数调用无法解析为重载函数,则会导致编译错误。
在下一课中,我们将探讨如何区分重载函数。然后,在随后的课程中,我们将探讨编译器如何将函数调用解析为重载函数。
总结
函数重载通过减少您需要记住的函数名称数量,提供了一种降低程序复杂性的好方法。它应该并且可以自由使用。
最佳实践
使用函数重载使您的程序更简单。