Menu
CoddyTech

算术运算符重载

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

像 +、-、* 和 / 这样的算术运算符通常会被重载,让自定义类的行为像内置数值类型一样。这些运算符通常会返回一个新对象,而不是修改操作数。

这是一个带有算术运算符的 Fraction 类:

class Fraction {
    int numerator, denominator;
    
public:
    Fraction(int n, int d) : numerator(n), denominator(d) {}
    
    Fraction operator+(const Fraction& other) const {
        return Fraction(
            numerator * other.denominator + other.numerator * denominator,
            denominator * other.denominator
        );
    }
    
    Fraction operator*(const Fraction& other) const {
        return Fraction(numerator * other.numerator, 
                        denominator * other.denominator);
    }
};

注意,这两个运算符都标记为 const,因为它们不会修改任何一个操作数。它们会创建并返回一个包含结果的新 Fraction。

对于像 += 这样的复合赋值运算符,写法有所不同。它们会修改左操作数,并返回对它的引用:

Fraction& operator+=(const Fraction& other) {
    numerator = numerator * other.denominator + other.numerator * denominator;
    denominator = denominator * other.denominator;
    return *this;
}

一种常见做法是通过复合赋值来实现基本运算符,从而减少代码重复:

Fraction operator+(const Fraction& other) const {
    Fraction result = *this;    // 复制这个对象
    result += other;            // 使用复合赋值
    return result;
}

这种方法可以确保两个运算符保持一致,也让维护更轻松。

challenge icon

挑战

简单

让我们构建一个 Money 类,通过重载算术运算符来处理货币计算。你将实现多个算术运算符,让你像处理普通数字一样自然地处理金额。

你将创建两个文件来组织代码:

  • Money.h:定义一个 Money 类,用分(以 int 类型存储)保存金额,以避免浮点精度问题。你的类应支持:
    • 一个构造函数,分别接收美元和美分两个整数
    • 一个 getter getDollars(),返回美元部分
    • 一个 getter getCents(),返回美分部分(0-99)
    • 重载 + 和 - 运算符,返回一个新的 Money 对象
    • 重载 += 和 -= 复合赋值运算符,修改当前对象并返回对它的引用
    • 一个 display() 方法,以 $X.YY 格式输出金额(美分始终显示为两位数)

    按照课中所示,通过复合赋值运算符实现基本运算符(+ 和 -),以减少重复代码。所有算术运算符都应在适当的位置标记为 const。

  • main.cpp:从输入中读取四个整数,表示两笔金额(dollars1、cents1、dollars2、cents2,每个整数单独一行)。创建两个 Money 对象,然后演示所有运算符:
    • 输出 "Amount 1: ",后面接第一笔金额
    • 输出 "Amount 2: ",后面接第二笔金额
    • 将两笔金额相加,并输出 "Sum: ",后面接结果
    • 用第一笔金额减去第二笔金额,并输出 "Difference: ",后面接结果
    • 使用 += 将第二笔金额加到第一笔金额上,然后输出 "After +=: ",后面接修改后的第一笔金额

对于 display() 方法,请使用 <iomanip> 中的 std::setw(2) 和 std::setfill('0'),确保美分始终显示为两位数(例如,$5.07,而不是 $5.7)。

使用 std::stoi() 将输入字符串转换为整数。别忘了在头文件中添加头文件保护。

亲手试试

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

using namespace std;

int main() {
    // 读取两笔金额的输入
    string line;
    
    getline(cin, line);
    int dollars1 = stoi(line);
    
    getline(cin, line);
    int cents1 = stoi(line);
    
    getline(cin, line);
    int dollars2 = stoi(line);
    
    getline(cin, line);
    int cents2 = stoi(line);
    
    // TODO: 用输入值创建两个 Money 对象
    
    // TODO: 打印 "Amount 1: ",然后显示第一笔金额
    
    // TODO: 打印 "Amount 2: ",然后显示第二笔金额
    
    // TODO: 将两笔金额相加,打印 "Sum: ",然后显示结果
    
    // TODO: 用第一笔金额减去第二笔金额,打印 "Difference: ",然后显示结果
    
    // TODO: 用 += 将第二笔金额加到第一笔金额上,然后打印 "After +=: ",再显示修改后的第一笔金额
    
    return 0;
}
quiz icon自我测试

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

面向对象编程中的所有课

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