函数重载
函数重载示例:
以下代码演示了文件范围内的 print 函数重载。
默认参数不被视为函数类型的一部分。 因此,它不用于选择重载函数。 仅在默认自变量上存在差异的两个函数被视为多个定义而不是重载函数。
不能为重载运算符提供默认参数。
// function_overloading.cpp
// compile with: /EHsc
#include <iostream>
#include <math.h>
#include <string>
// Prototype three print functions.
int print(std::string s); // Print a string.
int print(double dvalue); // Print a double.
int print(double dvalue, int prec); // Print a double with a
// given precision.
using namespace std;
int main(int argc, char *argv[])
{
const double d = 893094.2987;
if (argc < 2)
{
// These calls to print invoke print( char *s ).
print("This program requires one argument.");
print("The argument specifies the number of");
print("digits precision for the second number");
print("printed.");
exit(0);
}
// Invoke print( double dvalue ).
print(d);
// Invoke print( double dvalue, int prec ).
print(d, atoi(argv[1]));
}
// Print a string.
int print(string s)
{
cout << s << endl;
return cout.good();
}
// Print a double in default precision.
int print(double dvalue)
{
cout << dvalue << endl;
return cout.good();
}
// Print a double in specified precision.
// Positive numbers for precision indicate how many digits
// precision after the decimal point to show. Negative
// numbers for precision indicate where to round the number
// to the left of the decimal point.
int print(double dvalue, int prec)
{
// Use table-lookup for rounding/truncation.
static const double rgPow10[] = {
10E-7, 10E-6, 10E-5, 10E-4, 10E-3, 10E-2, 10E-1,
10E0, 10E1, 10E2, 10E3, 10E4, 10E5, 10E6 };
const int iPowZero = 6;
// If precision out of range, just print the number.
if (prec < -6 || prec > 7)
{
return print(dvalue);
}
// Scale, truncate, then rescale.
dvalue = floor(dvalue / rgPow10[iPowZero - prec]) *
rgPow10[iPowZero - prec];
cout << dvalue << endl;
return cout.good();
}
- 解释:C++ 允许同一范围内具有相同名称的多个函数的规范。 这些函数称为重载函数。 重载函数使你能够为函数提供不同的语义,具体取决于参数的类型和数量。
如, print 采用 std::string 自变量的函数执行的任务可能与使用类型的参数的任务不同 double 。 重载使您无需使用名称(如 print_string 或) print_double 。 在编译时,编译器根据调用方传入的参数类型选择要使用的重载。 如果调用 print(42.0) ,则 void print(double d) 将调用函数。 如果调用 print("hello world") ,则 void print(std::string) 将调用此重载。
可以重载成员函数和非成员函数。 下表显示了 C++ 使用函数声明的哪些部分来区分同一范围内具有相同名称的函数组。
重载注意事项 函数声明元素 是否用于重载? 函数返回类型 否 自变量的数量 是 自变量的类型 是 省略号存在或缺失 是 名称的使用 typedef 否 未指定的数组边界 否 const 或 volatile 是,应用于整个函数时 引用限定符 是
自变量匹配
选择重载函数以实现当前范围内的函数声明与函数调用中提供的参数的最佳匹配。 如果找到合适的函数,则调用该函数。 在此上下文中,"合适" 是指: - 找到完全匹配项。 - 已执行不重要的转换。 - 已执行整型提升。 - 已存在到所需自变量类型的标准转换。 - 已存在到所需参数类型的用户定义的转换(转换运算符或构造函数)。 - 已找到省略号所表示的自变量。 编译器为每个自变量创建一组候选函数。 候选函数是这样一种函数,其中的实际自变量可以转换为形式自变量的类型。
为每个自变量生成一组“最佳匹配函数”,并且所选函数是所有集的交集。 如果交集包含多个函数,则重载是不明确的并会生成错误。 对于至少一个自变量而言,最终选择的函数始终是比组中的所有其他函数更好的匹配项。 如果没有明确入选方,则函数调用会生成错误。
考虑下面的声明(针对下面的讨论中的标识,将函数标记为 Variant 1、Variant 2 和 Variant 3):
Fraction &Add( Fraction &f, long l ); // Variant 1
Fraction &Add( long l, Fraction &f ); // Variant 2
Fraction &Add( Fraction &f, Fraction &f ); // Variant 3
Fraction F1, F2;
//请考虑下列语句:
F1 = Add( F2, 23 );
前面的语句生成两个集:
|集 1:其第一个自变量的类型为 Fraction 的候选函数|设置2:可将第二个参数转换为类型的候选函数int
| |--------------------------------------------------------------------------|--------------------------------------------