S SmartDocs
Chuỗi bài: C++ cpp 420 dòng · Cập nhật 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;
}

Bài viết liên quan