Menu
CoddyTech

函数重载

本课属于 Coddy C++ 学习旅程的“面向对象编程”单元。第 57 课,共 104 课。

函数重载允许你定义多个名称相同但参数列表不同的函数。编译器会根据你传入的参数选择正确的版本。这是编译时多态的一种重要形式。

要让重载生效,函数的签名必须不同:参数的数量、类型,或两者都不同:

class Calculator {
public:
    int add(int a, int b) {
        return a + b;
    }
    
    double add(double a, double b) {
        return a + b;
    }
    
    int add(int a, int b, int c) {
        return a + b + c;
    }
};

Calculator calc;
calc.add(5, 3);        // 调用 add(int, int)
calc.add(2.5, 3.7);    // 调用 add(double, double)
calc.add(1, 2, 3);     // 调用 add(int, int, int)

编译器会检查每次调用,并将其匹配到合适的重载。这一过程完全在编译时进行,因此不会产生运行时开销。

重要:仅靠返回类型无法区分重载函数。下面的代码会导致编译器错误:

int getValue();
double getValue();  // 错误:不能仅根据返回类型进行重载

函数重载能让代码更直观。你不必创建 addInts、addDoubles 和 addThreeInts 这样的不同名称,而是使用一个有意义的名称,让编译器处理其余部分。

challenge icon

挑战

简单

让我们来创建一个消息格式化类,展示函数重载的强大之处。你将创建一个 Formatter 类,其中包含多个 format() 方法,用来处理不同类型的输入,让编译器根据你传入的内容选择正确的版本。

你需要将代码分别写在两个文件中:

  • Formatter.h:定义一个 Formatter 类,其中包含重载的 format() 方法,用来处理不同的情况:
    • 一个接收单个 std::string 并打印:Message: <text> 的方法
    • 一个接收 std::string 和 int 优先级的方法,打印:[Priority <priority>] <text>
    • 一个接收 std::string 和 double 时间戳的方法,打印:[<timestamp>s] <text>
    • 一个接收三个 std::string 参数(sender、receiver、message)并打印:From <sender> to <receiver>: <message> 的方法
    所有方法都应命名为 format():编译器会根据参数选择正确的方法。
  • main.cpp:读取 4 项输入(每项单独占一行):
    1. 一段简单的消息文本
    2. 一个优先级(整数)
    3. 一个时间戳(double)
    4. 一个发送者名称

    创建一个 Formatter 对象,并演示全部 4 个重载方法:

    • 仅使用消息文本调用 format()
    • 使用消息文本和优先级调用 format()
    • 使用消息文本和时间戳调用 format()
    • 使用发送者、将 "Admin" 作为接收者以及消息文本调用 format()

例如,输入 System ready、3、12.5 和 Server 时:

Message: System ready
[Priority 3] System ready
[12.5s] System ready
From Server to Admin: System ready

注意,你调用了 4 次同名方法 format(),但每次调用都会根据参数的类型和数量执行不同版本。这就是编译时多态:程序运行前,编译器就会确定使用哪个重载版本。

亲手试试

#include <iostream>
#include <string>
#include "Formatter.h"

using namespace std;

int main() {
    // 读取输入
    string message;
    getline(cin, message);
    
    int priority;
    cin >> priority;
    
    double timestamp;
    cin >> timestamp;
    cin.ignore();
    
    string sender;
    getline(cin, sender);
    
    // TODO: 创建一个 Formatter 对象
    
    // TODO: 仅用消息文本调用 format()
    
    // TODO: 用消息文本和 priority 调用 format()
    
    // TODO: 用消息文本和 timestamp 调用 format()
    
    // TODO: 用 sender、作为接收者的 "Admin" 和消息文本调用 format()
    
    return 0;
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: C++ 在线编译器