函数重载允许在同一作用域内声明多个同名函数,只要其参数列表在类型或个数上可区分。编译器根据实参类型与个数选择最匹配的版本(重载决议);仅返回值类型不同不能构成重载。本节在函数基础之上说明匹配规则、与 const 的关系及避免歧义的写法。

类型不同:基本示例

#include <iostream>

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

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

int main() {
    std::cout << max(3, 7) << " " << max(2.5, 1.1) << std::endl;
    return 0;
}

max(3, 7) 两个实参均为 int,选择整型版本;max(2.5, 1.1) 为 double,选择浮点版本。若写 max(3, 2.5),通常经隐式转换统一为浮点版本,具体以标准转换序为准。

参数个数不同

#include <iostream>
#include <string>

void print(int x) {
    std::cout << x << std::endl;
}

void print(int x, int y) {
    std::cout << x << ", " << y << std::endl;
}

void print(const std::string& s) {
    std::cout << s << std::endl;
}

调用 print(1)、print(1, 2)、print("hi") 分别匹配不同重载。字符串字面量可构造 std::string 匹配第三版。

决议规则(直观)

情况结果
存在唯一最佳匹配调用该重载
多个重载同样合适编译错误(歧义)
需要多级不相关转换才能匹配常报错或匹配失败
仅返回类型不同非法重载

设计接口时,不要让一次常见调用能同时套上两个重载、且编译器分不出谁更匹配。例如同时提供 void f(int) 与 void f(long),传入 short 时两边都要转换,可能直接报歧义,或选到你没预期的那一个。

const 与重载

非成员函数中,void g(int) 与 void g(const int) 对按值传递不构成有效重载(形参均为 int)。指针与引用类型的 const 位置不同会形成不同签名,例如 void h(int*) 与 void h(const int*)。成员函数可因 const 限定而重载(在类中),见类与对象。

与默认参数的关系

不要使“带默认参数的一个函数”与“另一个参数更少的重载”在相同调用形式下均可匹配,例如:

void f(int x);
void f(int x, int y = 0);  // 调用 f(1) 时歧义

默认参数的细节见默认参数一节;重载与默认参数应一并设计,避免重复表达同一调用路径。

何时不用重载

若各版本语义差异很大(例如 open 与 open_config),不同函数名往往更易读。重载适合“同一操作、不同类型或参数个数”的紧密族系,如 operator<< 对流与多种类型的输出。

本节说明了函数重载的动机与匹配方式。下一节介绍默认参数:为形参指定默认值以简化调用。