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++提供代码灵活性和可读性的重要机制:
重载类型
- 函数重载:相同名称,不同参数
- 运算符重载:为自定义类型定义运算符行为
- 转换重载:类型之间的自动或显式转换
重载解析优先级
- 精确匹配
- 提升转换(如char到int)
- 标准转换(如int到double)
- 用户定义转换
- 省略号匹配
最佳实践
- 保持运算符的直观语义
- 对称运算符使用友元函数
- 复合赋值运算符返回引用
- 避免重载&&、||、逗号运算符
- 谨慎使用隐式类型转换
重载让C++代码更加自然和直观,是构建用户友好API的重要工具。