C++中的算术运算符和重载最佳实践详解和代码示例
·
算术运算符
C++ 中的算术运算符是对基本数据类型进行数学运算的核心工具。包括加、减、乘、除、取模、递增/递减等操作。它们适用于内置类型,也可以通过重载应用于用户自定义类型(如类/结构体)。
1. 算术运算符一览表
| 运算符 | 含义 | 示例 | 支持类型 |
|---|---|---|---|
+ |
加法 | a + b |
数值/指针(偏移) |
- |
减法 | a - b |
数值/指针差 |
* |
乘法 | a * b |
数值 |
/ |
除法 | a / b |
数值(注意除以 0) |
% |
取模(余数) | a % b |
整数类型(不可用于浮点) |
++ |
自增(前/后) | ++a, a++ |
整型、指针等 |
-- |
自减(前/后) | --a, a-- |
整型、指针等 |
- |
一元负号 | -a |
数值 |
+ |
一元正号 | +a |
数值 |
2. 示例代码(基础类型)
#include <iostream>
using namespace std;
int main() {
int a = 10, b = 3;
cout << "a + b = " << a + b << endl;
cout << "a - b = " << a - b << endl;
cout << "a * b = " << a * b << endl;
cout << "a / b = " << a / b << endl; // 整数除法
cout << "a % b = " << a % b << endl; // 取模
float x = 5.0f, y = 2.0f;
cout << "x / y = " << x / y << endl; // 浮点除法
return 0;
}
3. 自增与自减(前置与后置)
int a = 5;
int b = ++a; // a=6, b=6(前置先加再赋值)
int c = a++; // a=7, c=6(后置先赋再加)
4. 算术运算符重载示例(复数类)
#include <iostream>
class Complex {
public:
double r, i;
Complex(double real, double imag) : r(real), i(imag) {}
// 重载加法
Complex operator+(const Complex& other) const {
return Complex(r + other.r, i + other.i);
}
// 重载乘法
Complex operator*(const Complex& other) const {
return Complex(r * other.r - i * other.i, r * other.i + i * other.r);
}
void print() const {
std::cout << r << " + " << i << "i" << std::endl;
}
};
int main() {
Complex a(2, 3), b(4, -1);
Complex c = a + b;
Complex d = a * b;
c.print(); // 输出:6 + 2i
d.print(); // 输出:11 + 10i
return 0;
}
5. 运算符优先级(部分)
| 优先级(高 → 低) | 运算符 | 说明 |
|---|---|---|
| 1 | ++, --, +, - |
一元运算 |
| 2 | *, /, % |
乘除取模 |
| 3 | +, - |
加减 |
| 4 | 赋值类 =, +=, -= |
赋值 |
可参考 C++ 运算符优先级表
6. 特殊注意事项
-
除法注意整数除法截断:
int a = 5, b = 2; cout << a / b << endl; // 输出 2(截断小数) -
取模只适用于整数。
-
浮点精度误差:
double x = 0.1 + 0.2; cout << x << endl; // 输出可能不是 0.3,而是 0.300000...
7. 总结
| 操作符 | 用途 | 是否可重载 | 注意点 |
|---|---|---|---|
+ - * / % |
基本算术 | ✅ | % 不适用浮点 |
++ -- |
自增自减 | ✅ | 前后置行为不同 |
+ - 一元 |
正负号 | ✅ | 可用作符号切换 |
| 重载 | 用户类型支持 | ✅ | 建议 const 成员,支持链式调用 |
C++ 算术运算符重载最佳实践
在 C++ 中,算术运算符重载允许用户让自定义类型(如复数、向量、矩阵、货币金额等)使用自然的数学符号(如 +, -, *, /)进行运算,就像内置类型一样。这提升了代码的可读性和可维护性,但也容易引入设计失误。
一、常见可重载的算术运算符
| 运算符 | 常用含义 |
|---|---|
+ |
加法 |
- |
减法 |
* |
乘法(标量乘法 / 点积 / 矩阵乘法) |
/ |
除法(标量除法) |
% |
模运算(一般不用重载) |
+= |
自加 |
-= |
自减 |
*= |
自乘 |
/= |
自除 |
二、重载方式选项:成员 vs 非成员
| 重载方式 | 使用情况 |
|---|---|
| 成员函数 | 修改当前对象(如 +=),或左值必须是类对象(如 this + other) |
| 非成员函数 | 支持 a + b,其中 a 不是类类型(如 int + MyClass) |
| 友元函数 | 需要访问私有成员时使用非成员 + friend |
最佳实践建议:
- 复合赋值运算符(
+=,*=等)使用成员函数实现; - 普通算术运算符(
+,*等)使用非成员函数,调用已有的复合赋值运算; - 适当使用
const和&引用避免复制。
三、最佳实践模板示例(二维向量)
#include <iostream>
class Vector2 {
public:
float x, y;
Vector2(float x = 0.0f, float y = 0.0f) : x(x), y(y) {}
// 复合赋值:成员函数
Vector2& operator+=(const Vector2& other) {
x += other.x;
y += other.y;
return *this;
}
Vector2& operator-=(const Vector2& other) {
x -= other.x;
y -= other.y;
return *this;
}
// 友元函数:普通加法
friend Vector2 operator+(Vector2 lhs, const Vector2& rhs) {
lhs += rhs; // 复用 +=
return lhs;
}
friend Vector2 operator-(Vector2 lhs, const Vector2& rhs) {
lhs -= rhs;
return lhs;
}
friend std::ostream& operator<<(std::ostream& os, const Vector2& v) {
return os << "(" << v.x << ", " << v.y << ")";
}
};
使用示例:
int main() {
Vector2 a(1, 2), b(3, 4);
Vector2 c = a + b;
Vector2 d = a - b;
std::cout << "a + b = " << c << "\n";
std::cout << "a - b = " << d << "\n";
}
四、最佳实践原则总结
| 原则 | 说明 |
|---|---|
| 复用已有实现 | 实现 + 时复用 +=(拷贝 + 复合操作) |
| 避免不必要复制 | 参数使用 const T&,返回值可按值返回(支持 RVO) |
| 提供对称性 | 实现 a + b 时,也考虑实现 b + a(如 int + MyClass) |
使用 friend 仅限必要时 |
只有当需要访问私有成员,且不能用 getter 替代时 |
| 不滥用重载 | 不要让 * 表示“加权平均”,符号语义要符合预期 |
始终支持 ostream << |
提升调试和输出体验(见上例) |
| 保持操作不可变性 | + 等操作符应当是不改变原对象的(除非是 +=) |
五、错误示例(反面教材)
Vector2 operator+(const Vector2& a, const Vector2& b) {
a += b; // 错误:不能修改 const 引用参数
return a;
}
修正方法:
Vector2 operator+(Vector2 a, const Vector2& b) {
a += b;
return a;
}
六、如何支持标量乘法(左乘/右乘)
friend Vector2 operator*(const Vector2& v, float scalar) {
return Vector2(v.x * scalar, v.y * scalar);
}
friend Vector2 operator*(float scalar, const Vector2& v) {
return v * scalar; // 复用上面的函数
}
七、C++20 三路比较
#include <compare>
class MyValue {
int val;
public:
auto operator<=>(const MyValue&) const = default; // C++20 自动生成比较
};
八、最终推荐设计模板
| 操作符 | 类型 | 实现方式 | 是否成员 |
|---|---|---|---|
+= |
复合赋值 | 成员函数 | ✅ |
+ |
通用加法 | 非成员 | ✅(友元) |
- |
通用减法 | 非成员 | ✅(友元) |
* |
标量或其他 | 非成员 | ✅ |
<< |
输出 | 非成员 | ✅(友元) |
更多推荐


所有评论(0)