考虑以下函数:
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;
}
但这样做需要:
- 维护一套一致的命名规则;
- 记住每个函数名;
- 在调用时选准正确的名字。
一旦需求扩展到“三个整数相加”,名字管理很快就会变得繁琐。
函数重载简介
C++ 提供了优雅的解决方案——函数重载 (function overloading):只要同名函数的参数类型不同(或可通过其他方式区分),即可在同一作用域内定义多个同名函数。这些同名函数称为重载函数(简称 overload)。
重载 add()
的示例:
double add(double x, double y)
{
return x + y;
}
现在作用域内有两个 add()
:
int add(int x, int y) // 整数版本
{
return x + y;
}
double add(double x, double y) // 浮点版本
{
return x + y;
}
int main()
{
return 0;
}
程序可正常编译。虽然看起来同名,但因参数类型不同,编译器能够区分它们,视为两个仅名字相同的独立函数。
关键洞察 只要重载函数能被编译器区分,就合法;否则产生编译错误。
相关内容 运算符亦可重载,见运算符重载简介。
重载决议简介
当调用重载函数时,编译器会根据实参匹配最合适的版本,这一过程称为重载决议 (overload resolution)。示例:
#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;
}
输出:
3
4.6
- 调用
add(1, 2)
时,实参为整数,匹配add(int, int)
。 - 调用
add(1.2, 3.4)
时,实参为浮点数,匹配add(double, double)
。
编译条件
使用重载函数的程序必须满足:
- 各重载函数必须可区分(见函数重载区分)。
- 每次调用必须能唯一匹配一个重载版本(见重载决议与二义性)。 否则编译报错。
下一课将探讨如何区分重载函数,再下一课研究编译器如何决议调用。
结论
函数重载通过减少需要记忆的函数名数量,显著降低程序复杂度,应当积极使用。
最佳实践
利用函数重载简化程序设计。