C++ 运算符重载入门:分数类实现示例
运算符重载是 C++ 的重要特性,它允许自定义类型像内置类型一样使用运算符。通过重载,可以让代码更直观易读,例如直接使用 + 号进行分数相加。
1. 理解运算符重载的基本概念
运算符重载本质上是为运算符赋予新的功能,使其能作用于自定义的类对象。例如,我们可以让两个分数对象直接用 + 号相加,而不需要调用类似 add() 这样的成员函数。
2. 创建基础分数类框架
首先定义一个 Fraction 类,包含分子 (numerator) 和分母 (denominator) 两个私有成员变量。构造函数负责初始化这两个值,同时加入一个约分函数来简化分数。
3. 实现约分功能
约分需要找到分子分母的最大公约数 (GCD),然后用它来约简分数。这里采用辗转相除法来计算 GCD,确保分数总是以最简形式存储。
#include <iostream>
#include <numeric>
class Fraction {
private:
int numerator;
int denominator;
// 计算最大公约数
static int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
// 约分函数
void simplify() {
if (denominator == 0) throw std::invalid_argument("Denominator cannot be zero");
int common = gcd(std::abs(numerator), std::abs(denominator));
numerator /= common;
denominator /= common;
if (denominator < 0) { // 保证分母为正
numerator = -numerator;
denominator = -denominator;
}
}
public:
Fraction(int n = 0, int d = 1) : numerator(n), denominator(d) {
simplify();
}
// 重载加法运算符 (+)
friend Fraction operator+(const Fraction& lhs, const Fraction& rhs) {
int newNum = lhs.numerator * rhs.denominator + rhs.numerator * lhs.denominator;
int newDen = lhs.denominator * rhs.denominator;
return Fraction(newNum, newDen);
}
// 重载减法运算符 (-)
friend Fraction operator-(const Fraction& lhs, const Fraction& rhs) {
int newNum = lhs.numerator * rhs.denominator - rhs.numerator * lhs.denominator;
int newDen = lhs.denominator * rhs.denominator;
return Fraction(newNum, newDen);
}
// 重载乘法运算符 (*)
friend Fraction operator*(const Fraction& lhs, const Fraction& rhs) {
int newNum = lhs.numerator * rhs.numerator;
int newDen = lhs.denominator * rhs.denominator;
return Fraction(newNum, newDen);
}
// 重载除法运算符 (/)
friend Fraction operator/(const Fraction& lhs, const Fraction& rhs) {
if (rhs.numerator == 0) throw std::invalid_argument("Division by zero");
int newNum = lhs.numerator * rhs.denominator;
int newDen = lhs.denominator * rhs.numerator;
return Fraction(newNum, newDen);
}
// 重载输出运算符 (<<)
friend std::ostream& operator<<(std::ostream& os, const Fraction& f) {
if (f.denominator == 1) {
os << f.numerator;
} else {
os << f.numerator << "/" << f.denominator;
}
return os;
}
};
int main() {
Fraction f1(1, 2); // 1/2
Fraction f2(1, 3); // 1/3
std::cout << "f1: " << f1 << std::endl;
std::cout << "f2: " << f2 << std::endl;
std::cout << "f1 + f2: " << (f1 + f2) << std::endl;
std::cout << "f1 - f2: " << (f1 - f2) << std::endl;
std::cout << "f1 * f2: " << (f1 * f2) << std::endl;
std::cout << "f1 / f2: " << (f1 / f2) << std::endl;
return 0;
}
4. 测试所有运算符
在 main 函数中创建几个 Fraction 对象,测试各种运算符的重载效果,确保计算结果正确且格式美观。
整个实现过程中,运算符重载让分数运算的代码更加直观易读。比如计算 (a + b) * c - d 这样的表达式,现在可以直接写成数学上的形式,而不需要嵌套多个函数调用。通过这个分数类的例子,不仅理解了运算符重载的语法,更重要的是学会了如何设计类来模拟现实世界的数学概念。建议初学者可以从这种具体的例子入手,逐步掌握 C++ 的这个强大特性。

