Série: C++
cpp
420 lignes
· Mis à jour 2026-04-03
operator_overload.cpp
C++/Part2_物件導向/Ch11_運算子多載/operator_overload.cpp
// ============================================================
// Ch11 — operator_overload.cpp
// 運算子多載:Vector2D 與 Fraction 類別的完整示範
// 編譯:g++ -std=c++17 -Wall -o operator_overload operator_overload.cpp
// ============================================================
#include <iostream>
#include <cmath>
#include <numeric> // std::gcd (C++17)
#include <stdexcept>
// ────────────────────────────────────────────────────────────
// 1. Vector2D — 二維向量,示範算術與比較運算子
// ────────────────────────────────────────────────────────────
class Vector2D {
public:
double x, y;
Vector2D() : x(0), y(0) {}
Vector2D(double x, double y) : x(x), y(y) {}
// ── 算術運算子(成員函式)──
Vector2D operator+(const Vector2D& rhs) const {
return {x + rhs.x, y + rhs.y};
}
Vector2D operator-(const Vector2D& rhs) const {
return {x - rhs.x, y - rhs.y};
}
// 向量與純量相乘
Vector2D operator*(double scalar) const {
return {x * scalar, y * scalar};
}
// 內積
double operator*(const Vector2D& rhs) const {
return x * rhs.x + y * rhs.y;
}
// 負號(一元運算子)
Vector2D operator-() const {
return {-x, -y};
}
// ── 複合指派運算子 ──
Vector2D& operator+=(const Vector2D& rhs) {
x += rhs.x;
y += rhs.y;
return *this;
}
Vector2D& operator-=(const Vector2D& rhs) {
x -= rhs.x;
y -= rhs.y;
return *this;
}
Vector2D& operator*=(double scalar) {
x *= scalar;
y *= scalar;
return *this;
}
// ── 比較運算子 ──
bool operator==(const Vector2D& rhs) const {
constexpr double eps = 1e-9;
return std::abs(x - rhs.x) < eps && std::abs(y - rhs.y) < eps;
}
bool operator!=(const Vector2D& rhs) const {
return !(*this == rhs);
}
// ── 下標運算子 ──
double& operator[](int index) {
if (index == 0) return x;
if (index == 1) return y;
throw std::out_of_range("Vector2D 索引必須為 0 或 1");
}
const double& operator[](int index) const {
if (index == 0) return x;
if (index == 1) return y;
throw std::out_of_range("Vector2D 索引必須為 0 或 1");
}
// ── 輔助方法 ──
double magnitude() const {
return std::sqrt(x * x + y * y);
}
// ── 串流運算子(friend 非成員)──
friend std::ostream& operator<<(std::ostream& os, const Vector2D& v) {
os << "(" << v.x << ", " << v.y << ")";
return os;
}
};
// 純量 * 向量(左運算元非 Vector2D,必須用非成員函式)
Vector2D operator*(double scalar, const Vector2D& v) {
return {scalar * v.x, scalar * v.y};
}
// ────────────────────────────────────────────────────────────
// 2. Fraction — 分數類別,示範完整運算子組合
// ────────────────────────────────────────────────────────────
class Fraction {
public:
Fraction(int num = 0, int den = 1) : num_(num), den_(den) {
if (den_ == 0) throw std::invalid_argument("分母不可為零");
reduce();
}
// ── 算術運算子 ──
Fraction operator+(const Fraction& rhs) const {
return Fraction(num_ * rhs.den_ + rhs.num_ * den_,
den_ * rhs.den_);
}
Fraction operator-(const Fraction& rhs) const {
return Fraction(num_ * rhs.den_ - rhs.num_ * den_,
den_ * rhs.den_);
}
Fraction operator*(const Fraction& rhs) const {
return Fraction(num_ * rhs.num_, den_ * rhs.den_);
}
Fraction operator/(const Fraction& rhs) const {
if (rhs.num_ == 0) throw std::invalid_argument("除以零");
return Fraction(num_ * rhs.den_, den_ * rhs.num_);
}
// 負號
Fraction operator-() const {
return Fraction(-num_, den_);
}
// ── 複合指派 ──
Fraction& operator+=(const Fraction& rhs) {
*this = *this + rhs;
return *this;
}
Fraction& operator-=(const Fraction& rhs) {
*this = *this - rhs;
return *this;
}
Fraction& operator*=(const Fraction& rhs) {
*this = *this * rhs;
return *this;
}
Fraction& operator/=(const Fraction& rhs) {
*this = *this / rhs;
return *this;
}
// ── 比較運算子 ──
bool operator==(const Fraction& rhs) const {
return num_ == rhs.num_ && den_ == rhs.den_;
}
bool operator!=(const Fraction& rhs) const {
return !(*this == rhs);
}
bool operator<(const Fraction& rhs) const {
return static_cast<long long>(num_) * rhs.den_ <
static_cast<long long>(rhs.num_) * den_;
}
bool operator>(const Fraction& rhs) const {
return rhs < *this;
}
bool operator<=(const Fraction& rhs) const {
return !(rhs < *this);
}
bool operator>=(const Fraction& rhs) const {
return !(*this < rhs);
}
// ── 前綴與後綴遞增遞減 ──
// 前綴 ++f
Fraction& operator++() {
num_ += den_;
return *this;
}
// 後綴 f++
Fraction operator++(int) {
Fraction old = *this;
num_ += den_;
return old;
}
// 前綴 --f
Fraction& operator--() {
num_ -= den_;
return *this;
}
// 後綴 f--
Fraction operator--(int) {
Fraction old = *this;
num_ -= den_;
return old;
}
// ── 型別轉換 ──
explicit operator double() const {
return static_cast<double>(num_) / den_;
}
explicit operator bool() const {
return num_ != 0;
}
// ── 存取器 ──
int num() const { return num_; }
int den() const { return den_; }
// ── 串流運算子 ──
friend std::ostream& operator<<(std::ostream& os, const Fraction& f) {
if (f.den_ == 1) {
os << f.num_;
} else {
os << f.num_ << "/" << f.den_;
}
return os;
}
friend std::istream& operator>>(std::istream& is, Fraction& f) {
int n, d;
char slash;
is >> n >> slash >> d;
f = Fraction(n, d);
return is;
}
private:
int num_, den_;
void reduce() {
if (den_ < 0) { num_ = -num_; den_ = -den_; }
int g = std::gcd(std::abs(num_), den_);
num_ /= g;
den_ /= g;
}
};
// ============================================================
// main
// ============================================================
int main() {
std::cout << "========================================\n";
std::cout << " 1. Vector2D 運算子多載\n";
std::cout << "========================================\n";
{
Vector2D a(3.0, 4.0);
Vector2D b(1.0, 2.0);
std::cout << " a = " << a << "\n";
std::cout << " b = " << b << "\n";
std::cout << " a + b = " << (a + b) << "\n";
std::cout << " a - b = " << (a - b) << "\n";
std::cout << " a * 2.0 = " << (a * 2.0) << "\n";
std::cout << " 3.0 * b = " << (3.0 * b) << "\n";
std::cout << " a 內積 b = " << (a * b) << "\n";
std::cout << " -a = " << (-a) << "\n";
std::cout << " |a| = " << a.magnitude() << "\n";
std::cout << "\n a[0] = " << a[0] << ", a[1] = " << a[1] << "\n";
a += b;
std::cout << " a += b → a = " << a << "\n";
a *= 0.5;
std::cout << " a *= 0.5 → a = " << a << "\n";
std::cout << " a == b? " << (a == b ? "是" : "否") << "\n";
std::cout << " a != b? " << (a != b ? "是" : "否") << "\n";
}
std::cout << "\n========================================\n";
std::cout << " 2. Fraction 運算子多載\n";
std::cout << "========================================\n";
{
Fraction a(1, 3);
Fraction b(2, 5);
std::cout << " a = " << a << "\n";
std::cout << " b = " << b << "\n";
std::cout << " a + b = " << (a + b) << "\n";
std::cout << " a - b = " << (a - b) << "\n";
std::cout << " a * b = " << (a * b) << "\n";
std::cout << " a / b = " << (a / b) << "\n";
std::cout << " -a = " << (-a) << "\n";
}
std::cout << "\n========================================\n";
std::cout << " 3. Fraction 比較運算子\n";
std::cout << "========================================\n";
{
Fraction a(1, 2);
Fraction b(2, 4);
Fraction c(3, 4);
std::cout << " " << a << " == " << b << "? "
<< (a == b ? "是" : "否") << " (約分後相等)\n";
std::cout << " " << a << " != " << c << "? "
<< (a != c ? "是" : "否") << "\n";
std::cout << " " << a << " < " << c << "? "
<< (a < c ? "是" : "否") << "\n";
std::cout << " " << c << " > " << a << "? "
<< (c > a ? "是" : "否") << "\n";
std::cout << " " << a << " <= " << b << "? "
<< (a <= b ? "是" : "否") << "\n";
}
std::cout << "\n========================================\n";
std::cout << " 4. 前綴與後綴 ++ / --\n";
std::cout << "========================================\n";
{
Fraction f(3, 4);
std::cout << " f = " << f << "\n";
std::cout << " ++f = " << (++f) << "\n"; // 3/4 + 1 = 7/4
std::cout << " f 現在 = " << f << "\n";
std::cout << " f++ = " << (f++) << "\n"; // 回傳 7/4,f 變 11/4
std::cout << " f 現在 = " << f << "\n";
std::cout << " --f = " << (--f) << "\n"; // 11/4 - 1 = 7/4
std::cout << " f 現在 = " << f << "\n";
std::cout << " f-- = " << (f--) << "\n"; // 回傳 7/4,f 變 3/4
std::cout << " f 現在 = " << f << "\n";
}
std::cout << "\n========================================\n";
std::cout << " 5. 型別轉換運算子\n";
std::cout << "========================================\n";
{
Fraction f(3, 4);
double d = static_cast<double>(f); // explicit 轉換
std::cout << " " << f << " 轉為 double = " << d << "\n";
Fraction zero(0, 1);
std::cout << " " << f << " 轉為 bool = "
<< (static_cast<bool>(f) ? "true" : "false") << "\n";
std::cout << " " << zero << " 轉為 bool = "
<< (static_cast<bool>(zero) ? "true" : "false") << "\n";
// explicit bool 在 if 中可隱式使用
if (f) {
std::cout << " " << f << " 在 if 中被視為 true\n";
}
}
std::cout << "\n========================================\n";
std::cout << " 6. 複合指派運算子\n";
std::cout << "========================================\n";
{
Fraction f(1, 6);
std::cout << " f = " << f << "\n";
f += Fraction(1, 3);
std::cout << " f += 1/3 → " << f << "\n";
f -= Fraction(1, 6);
std::cout << " f -= 1/6 → " << f << "\n";
f *= Fraction(2, 1);
std::cout << " f *= 2 → " << f << "\n";
f /= Fraction(3, 1);
std::cout << " f /= 3 → " << f << "\n";
}
std::cout << "\n========================================\n";
std::cout << " 7. 連鎖運算\n";
std::cout << "========================================\n";
{
Fraction a(1, 2), b(1, 3), c(1, 6);
Fraction result = a + b + c;
std::cout << " " << a << " + " << b << " + " << c
<< " = " << result << "\n";
result = a * b - c;
std::cout << " " << a << " * " << b << " - " << c
<< " = " << result << "\n";
}
std::cout << "\n========================================\n";
std::cout << " 程式結束\n";
std::cout << "========================================\n";
return 0;
}
Articles liés
C++
c
Mis à jour 2026-07-21
deviceAlpha.h
deviceAlpha.h — c source code from the C++ learning materials (C++/Mavis_Homework/FinalProject/deviceAlpha.h).
Lire l'article →
C++
c
Mis à jour 2026-07-21
finalproject.c
finalproject.c — c source code from the C++ learning materials (C++/Mavis_Homework/FinalProject/finalproject.c).
Lire l'article →
C++
cpp
Mis à jour 2026-07-21
finalproject.cpp
finalproject.cpp — cpp source code from the C++ learning materials (C++/Mavis_Homework/FinalProject/finalproject.cpp).
Lire l'article →
C++
c
Mis à jour 2026-07-21
deviceAlpha.h
deviceAlpha.h — c source code from the C++ learning materials (C++/Mavis_Homework/Lab8/deviceAlpha.h).
Lire l'article →
C++
c
Mis à jour 2026-07-21
lab8.c
lab8.c — c source code from the C++ learning materials (C++/Mavis_Homework/Lab8/lab8.c).
Lire l'article →
C++
cpp
Mis à jour 2026-07-21
lab8.cpp
lab8.cpp — cpp source code from the C++ learning materials (C++/Mavis_Homework/Lab8/lab8.cpp).
Lire l'article →