Skip to content

C++ 重载

概述

重载(Overloading)是C++的重要特性,允许在相同作用域内使用相同的名称定义多个函数或运算符,但它们具有不同的参数列表。重载提供了编程的灵活性和代码的可读性,包括函数重载和运算符重载两种形式。

🔧 函数重载

基本函数重载

cpp
#include <iostream>
#include <string>
#include <vector>

class Calculator {
public:
    // 整数加法
    int add(int a, int b) {
        std::cout << "整数加法: ";
        return a + b;
    }
    
    // 浮点数加法
    double add(double a, double b) {
        std::cout << "浮点数加法: ";
        return a + b;
    }
    
    // 三个参数加法
    int add(int a, int b, int c) {
        std::cout << "三数加法: ";
        return a + b + c;
    }
    
    // 字符串连接
    std::string add(const std::string& a, const std::string& b) {
        std::cout << "字符串连接: ";
        return a + b;
    }
    
    // 数组求和
    int add(const std::vector<int>& numbers) {
        std::cout << "数组求和: ";
        int sum = 0;
        for (int num : numbers) {
            sum += num;
        }
        return sum;
    }
};

int main() {
    std::cout << "=== 函数重载 ===" << std::endl;
    
    Calculator calc;
    
    std::cout << calc.add(5, 3) << std::endl;
    std::cout << calc.add(2.5, 3.7) << std::endl;
    std::cout << calc.add(1, 2, 3) << std::endl;
    std::cout << calc.add(std::string("Hello"), std::string(" World")) << std::endl;
    
    std::vector<int> nums = {1, 2, 3, 4, 5};
    std::cout << calc.add(nums) << std::endl;
    
    return 0;
}

重载解析规则

cpp
#include <iostream>

void print(int x) {
    std::cout << "print(int): " << x << std::endl;
}

void print(double x) {
    std::cout << "print(double): " << x << std::endl;
}

void print(const char* x) {
    std::cout << "print(const char*): " << x << std::endl;
}

void print(const std::string& x) {
    std::cout << "print(string): " << x << std::endl;
}

// const重载
void process(int& x) {
    std::cout << "process(int&): " << x << std::endl;
    x *= 2;
}

void process(const int& x) {
    std::cout << "process(const int&): " << x << std::endl;
}

int main() {
    std::cout << "=== 重载解析 ===" << std::endl;
    
    // 精确匹配
    print(42);              // int
    print(3.14);            // double
    print("Hello");         // const char*
    print(std::string("World")); // string
    
    // 类型转换
    print(3.14f);           // float -> double
    print('A');             // char -> int
    
    // const重载
    int mutable_var = 10;
    const int const_var = 20;
    
    process(mutable_var);   // 调用非const版本
    process(const_var);     // 调用const版本
    process(100);           // 临时对象,调用const版本
    
    std::cout << "修改后的值: " << mutable_var << std::endl;
    
    return 0;
}

⚙️ 运算符重载

基本运算符重载

cpp
#include <iostream>

class Complex {
private:
    double real_, imag_;
    
public:
    Complex(double real = 0, double imag = 0) : real_(real), imag_(imag) {}
    
    // 加法运算符重载(成员函数)
    Complex operator+(const Complex& other) const {
        return Complex(real_ + other.real_, imag_ + other.imag_);
    }
    
    // 减法运算符重载
    Complex operator-(const Complex& other) const {
        return Complex(real_ - other.real_, imag_ - other.imag_);
    }
    
    // 乘法运算符重载
    Complex operator*(const Complex& other) const {
        return Complex(real_ * other.real_ - imag_ * other.imag_,
                      real_ * other.imag_ + imag_ * other.real_);
    }
    
    // 赋值运算符重载
    Complex& operator=(const Complex& other) {
        if (this != &other) {
            real_ = other.real_;
            imag_ = other.imag_;
        }
        return *this;
    }
    
    // 复合赋值运算符
    Complex& operator+=(const Complex& other) {
        real_ += other.real_;
        imag_ += other.imag_;
        return *this;
    }
    
    // 比较运算符
    bool operator==(const Complex& other) const {
        return real_ == other.real_ && imag_ == other.imag_;
    }
    
    bool operator!=(const Complex& other) const {
        return !(*this == other);
    }
    
    // 一元运算符
    Complex operator-() const {
        return Complex(-real_, -imag_);
    }
    
    Complex& operator++() {  // 前缀++
        ++real_;
        return *this;
    }
    
    Complex operator++(int) {  // 后缀++
        Complex temp = *this;
        ++real_;
        return temp;
    }
    
    // 访问器
    double real() const { return real_; }
    double imag() const { return imag_; }
    
    void display() const {
        std::cout << real_;
        if (imag_ >= 0) std::cout << " + ";
        else std::cout << " - ";
        std::cout << std::abs(imag_) << "i";
    }
};

// 友元函数重载输出运算符
std::ostream& operator<<(std::ostream& os, const Complex& c) {
    os << c.real();
    if (c.imag() >= 0) os << " + ";
    else os << " - ";
    os << std::abs(c.imag()) << "i";
    return os;
}

int main() {
    std::cout << "=== 运算符重载 ===" << std::endl;
    
    Complex c1(3, 4);
    Complex c2(1, 2);
    
    std::cout << "c1 = " << c1 << std::endl;
    std::cout << "c2 = " << c2 << std::endl;
    
    // 算术运算
    Complex c3 = c1 + c2;
    std::cout << "c1 + c2 = " << c3 << std::endl;
    
    Complex c4 = c1 - c2;
    std::cout << "c1 - c2 = " << c4 << std::endl;
    
    Complex c5 = c1 * c2;
    std::cout << "c1 * c2 = " << c5 << std::endl;
    
    // 复合赋值
    c1 += c2;
    std::cout << "c1 += c2: " << c1 << std::endl;
    
    // 一元运算符
    Complex c6 = -c2;
    std::cout << "-c2 = " << c6 << std::endl;
    
    // 自增运算符
    std::cout << "++c2 = " << ++c2 << std::endl;
    std::cout << "c2++ = " << c2++ << ", c2 = " << c2 << std::endl;
    
    return 0;
}

下标和函数调用运算符

cpp
#include <iostream>
#include <vector>
#include <stdexcept>

class Matrix {
private:
    std::vector<std::vector<int>> data_;
    size_t rows_, cols_;
    
public:
    Matrix(size_t rows, size_t cols, int init_value = 0) 
        : rows_(rows), cols_(cols) {
        data_.resize(rows_, std::vector<int>(cols_, init_value));
    }
    
    // 下标运算符重载
    std::vector<int>& operator[](size_t row) {
        return data_[row];
    }
    
    const std::vector<int>& operator[](size_t row) const {
        return data_[row];
    }
    
    // 函数调用运算符重载
    int& operator()(size_t row, size_t col) {
        if (row >= rows_ || col >= cols_) {
            throw std::out_of_range("矩阵索引越界");
        }
        return data_[row][col];
    }
    
    const int& operator()(size_t row, size_t col) const {
        if (row >= rows_ || col >= cols_) {
            throw std::out_of_range("矩阵索引越界");
        }
        return data_[row][col];
    }
    
    void display() const {
        for (size_t i = 0; i < rows_; ++i) {
            for (size_t j = 0; j < cols_; ++j) {
                std::cout << data_[i][j] << " ";
            }
            std::cout << std::endl;
        }
    }
    
    size_t rows() const { return rows_; }
    size_t cols() const { return cols_; }
};

// 函数对象示例
class Multiplier {
private:
    int factor_;
    
public:
    Multiplier(int factor) : factor_(factor) {}
    
    // 函数调用运算符
    int operator()(int value) const {
        return value * factor_;
    }
};

int main() {
    std::cout << "=== 下标和函数调用运算符 ===" << std::endl;
    
    // 矩阵示例
    Matrix matrix(3, 3);
    
    // 使用下标运算符
    matrix[0][0] = 1;
    matrix[1][1] = 5;
    matrix[2][2] = 9;
    
    // 使用函数调用运算符
    matrix(0, 1) = 2;
    matrix(1, 0) = 4;
    
    std::cout << "矩阵内容:" << std::endl;
    matrix.display();
    
    // 函数对象
    Multiplier times3(3);
    std::cout << "5 * 3 = " << times3(5) << std::endl;
    std::cout << "7 * 3 = " << times3(7) << std::endl;
    
    return 0;
}

类型转换运算符

cpp
#include <iostream>
#include <string>

class Temperature {
private:
    double celsius_;
    
public:
    explicit Temperature(double celsius) : celsius_(celsius) {}
    
    // 类型转换运算符
    operator double() const {
        return celsius_;
    }
    
    operator int() const {
        return static_cast<int>(celsius_);
    }
    
    operator std::string() const {
        return std::to_string(celsius_) + "°C";
    }
    
    // 显式转换函数
    double toFahrenheit() const {
        return celsius_ * 9.0 / 5.0 + 32.0;
    }
    
    double toKelvin() const {
        return celsius_ + 273.15;
    }
    
    double getCelsius() const { return celsius_; }
};

class Distance {
private:
    double meters_;
    
public:
    explicit Distance(double meters) : meters_(meters) {}
    
    // 构造函数可以作为转换函数
    static Distance fromKilometers(double km) {
        return Distance(km * 1000);
    }
    
    static Distance fromMiles(double miles) {
        return Distance(miles * 1609.34);
    }
    
    double toKilometers() const { return meters_ / 1000; }
    double toMiles() const { return meters_ / 1609.34; }
    double getMeters() const { return meters_; }
    
    // 类型转换运算符
    operator double() const { return meters_; }
};

int main() {
    std::cout << "=== 类型转换运算符 ===" << std::endl;
    
    Temperature temp(25.5);
    
    // 隐式类型转换
    double temp_double = temp;
    int temp_int = temp;
    std::string temp_str = temp;
    
    std::cout << "温度(double): " << temp_double << std::endl;
    std::cout << "温度(int): " << temp_int << std::endl;
    std::cout << "温度(string): " << temp_str << std::endl;
    
    // 显式转换
    std::cout << "华氏温度: " << temp.toFahrenheit() << "°F" << std::endl;
    std::cout << "开尔文温度: " << temp.toKelvin() << "K" << std::endl;
    
    // 距离转换
    Distance d1(1000);  // 1000米
    Distance d2 = Distance::fromKilometers(2.5);  // 2.5公里
    
    std::cout << "d1: " << d1.getMeters() << "米" << std::endl;
    std::cout << "d2: " << d2.toKilometers() << "公里" << std::endl;
    
    double total_meters = d1 + d2;  // 隐式转换为double
    std::cout << "总距离: " << total_meters << "米" << std::endl;
    
    return 0;
}

📋 重载规则和最佳实践

运算符重载指南

cpp
#include <iostream>
#include <string>

class Point {
private:
    double x_, y_;
    
public:
    Point(double x = 0, double y = 0) : x_(x), y_(y) {}
    
    // 可重载的运算符示例
    Point operator+(const Point& other) const {
        return Point(x_ + other.x_, y_ + other.y_);
    }
    
    Point& operator+=(const Point& other) {
        x_ += other.x_;
        y_ += other.y_;
        return *this;
    }
    
    bool operator==(const Point& other) const {
        return x_ == other.x_ && y_ == other.y_;
    }
    
    // 友元函数用于对称运算符
    friend Point operator*(double scale, const Point& p) {
        return Point(scale * p.x_, scale * p.y_);
    }
    
    Point operator*(double scale) const {
        return Point(scale * x_, scale * y_);
    }
    
    // 流运算符
    friend std::ostream& operator<<(std::ostream& os, const Point& p) {
        os << "(" << p.x_ << ", " << p.y_ << ")";
        return os;
    }
    
    friend std::istream& operator>>(std::istream& is, Point& p) {
        is >> p.x_ >> p.y_;
        return is;
    }
    
    double getX() const { return x_; }
    double getY() const { return y_; }
};

int main() {
    std::cout << "=== 运算符重载最佳实践 ===" << std::endl;
    
    Point p1(3, 4);
    Point p2(1, 2);
    
    std::cout << "p1 = " << p1 << std::endl;
    std::cout << "p2 = " << p2 << std::endl;
    
    // 算术运算
    Point p3 = p1 + p2;
    std::cout << "p1 + p2 = " << p3 << std::endl;
    
    // 复合赋值
    p1 += p2;
    std::cout << "p1 += p2: " << p1 << std::endl;
    
    // 数乘
    Point p4 = p2 * 2.0;
    Point p5 = 3.0 * p2;
    std::cout << "p2 * 2.0 = " << p4 << std::endl;
    std::cout << "3.0 * p2 = " << p5 << std::endl;
    
    // 比较
    std::cout << "p4 == p5: " << (p4 == p5) << std::endl;
    
    std::cout << "\n=== 重载规则 ===" << std::endl;
    std::cout << "✓ 可重载: +, -, *, /, %, ^, &, |, ~, !, =, <, >, +=, -=, *=, /=, %=, ^=, &=, |=, <<, >>, >>=, <<=, ==, !=, <=, >=, &&, ||, ++, --, ,, ->*, ->, (), []" << std::endl;
    std::cout << "✗ 不可重载: ::, ., .*, ?:" << std::endl;
    std::cout << "📌 建议: 保持运算符的直观含义" << std::endl;
    std::cout << "📌 建议: 对称运算符使用友元函数" << std::endl;
    std::cout << "📌 建议: 复合赋值返回引用" << std::endl;
    
    return 0;
}

总结

重载是C++提供代码灵活性和可读性的重要机制:

重载类型

  • 函数重载:相同名称,不同参数
  • 运算符重载:为自定义类型定义运算符行为
  • 转换重载:类型之间的自动或显式转换

重载解析优先级

  1. 精确匹配
  2. 提升转换(如char到int)
  3. 标准转换(如int到double)
  4. 用户定义转换
  5. 省略号匹配

最佳实践

  • 保持运算符的直观语义
  • 对称运算符使用友元函数
  • 复合赋值运算符返回引用
  • 避免重载&&、||、逗号运算符
  • 谨慎使用隐式类型转换

重载让C++代码更加自然和直观,是构建用户友好API的重要工具。

本站内容仅供学习和研究使用。