在 C++ 中,递增运算符(++) 分为前置递增(++obj) 和后置递增(obj++),两者语义不同,重载方式也有明显区别。递增运算符是单目运算符,通常重载为类的成员函数(更符合语义,因为操作数是类对象本身),也可重载为全局函数(极少用)。
一、核心区别:前置 vs 后置递增

二、重载语法(成员函数方式,推荐)
- 前置递增重载
cpp
// 类内声明
类名& operator++();
// 类外定义
类名& 类名::operator++() {
// 1. 修改对象内部状态(如数值+1)
// 2. 返回自身引用(*this)
return *this;
}
- 后置递增重载
cpp
// 类内声明(int是占位符,无实际意义,仅用于区分前置)
类名 operator++(int);
// 类外定义
类名 类名::operator++(int) {
// 1. 保存当前对象的副本(临时对象)
类名 temp = *this;
// 2. 修改原对象状态
// 3. 返回副本(原状态)
return temp;
}
三、基础示例:整数包装类重载 ++
以自定义整数类 MyInt 为例,实现前置 / 后置递增:
cpp
#include <iostream>
using namespace std;
class MyInt {
private:
int val; // 封装的整数值
public:
// 构造函数
MyInt(int v = 0) : val(v) {}
// 1. 重载前置递增(返回引用)
MyInt& operator++() {
val++; // 先加1
return *this; // 返回自身,支持链式操作
}
// 2. 重载后置递增(int占位符,返回值)
MyInt operator++(int) {
MyInt temp = *this; // 保存当前值
val++; // 后加1
return temp; // 返回原状态
}
// 辅助:输出重载(方便打印)
friend ostream& operator<<(ostream& os, const MyInt& mi) {
os << mi.val;
return os;
}
};
int main() {
MyInt a(5);
// 前置递增:先加1,再使用
cout << "++a = " << ++a << endl; // 输出:++a = 6
cout << "a = " << a << endl; // 输出:a = 6
// 后置递增:先使用,再加1
cout << "a++ = " << a++ << endl; // 输出:a++ = 6
cout << "a = " << a << endl; // 输出:a = 7
// 前置支持链式操作
MyInt b(10);
cout << "++(++b) = " << ++(++b) << endl; // 输出:++(++b) = 12
return 0;
}
四、进阶示例:复数类递增(实部 + 虚部同时 + 1)
cpp
#include <iostream>
using namespace std;
class Complex {
private:
double real; // 实部
double imag; // 虚部
public:
Complex(double r = 0, double i = 0) : real(r), imag(i) {}
// 前置递增:实部、虚部都+1,返回引用
Complex& operator++() {
real++;
imag++;
return *this;
}
// 后置递增:返回原状态,再修改
Complex operator++(int) {
Complex temp = *this;
real++;
imag++;
return temp;
}
// 输出重载
friend ostream& operator<<(ostream& os, const Complex& c) {
os << real << " + " << imag << "i";
return os;
}
};
int main() {
Complex c(1.5, 2.5);
cout << "++c = " << ++c << endl; // 输出:++c = 2.5 + 3.5i
cout << "c++ = " << c++ << endl; // 输出:c++ = 2.5 + 3.5i
cout << "c = " << c << endl; // 输出:c = 3.5 + 4.5i
return 0;
}
五、全局函数重载(极少用,了解即可)
若需重载为全局函数(需访问私有成员时声明为友元),语法如下:
cpp
#include <iostream>
using namespace std;
class MyInt {
private:
int val;
public:
MyInt(int v = 0) : val(v) {}
// 声明友元:前置递增
friend MyInt& operator++(MyInt& mi);
// 声明友元:后置递增
friend MyInt operator++(MyInt& mi, int);
friend ostream& operator<<(ostream& os, const MyInt& mi) {
os << mi.val;
return os;
}
};
// 全局定义前置递增
MyInt& operator++(MyInt& mi) {
mi.val++;
return mi;
}
// 全局定义后置递增
MyInt operator++(MyInt& mi, int) {
MyInt temp = mi;
mi.val++;
return temp;
}
int main() {
MyInt a(5);
cout << ++a << endl; // 6
cout << a++ << endl; // 6
cout << a << endl; // 7
return 0;
}
六、常见误区与注意事项
1、后置递增的 int 占位符:
这个 int 只是语法标记,无实际参数传递,不能省略(否则编译器无法区分前置 / 后置);
无需给 int 命名(如 operator++(int) 即可,不用写 operator++(int flag))。
2、返回值错误:
前置递增必须返回引用(MyInt&):若返回值,会生成临时对象,链式操作(++(++a))会修改临时对象,而非原对象;
后置递增必须返回值(MyInt):若返回引用,会返回临时对象的引用(临时对象销毁后,引用悬空,导致未定义行为)。
3、修改原对象的语义:
递增运算符的核心是 "修改对象自身",因此优先重载为成员函数(全局函数需传引用,语义不如成员函数直观)。
与 += 配合:若类已有 += 重载,可复用逻辑:
cpp
MyInt& operator++() {
*this += 1; // 复用 += 逻辑
return *this;
}
七、递减运算符(--)重载
递减运算符(--)的重载逻辑与递增完全一致,仅需将 "+1" 改为 "-1":
cpp
// 前置递减
MyInt& operator--() {
val--;
return *this;
}
// 后置递减
MyInt operator--(int) {
MyInt temp = *this;
val--;
return temp;
}
总结
递增运算符重载分前置和后置,核心区别是返回值类型和执行顺序;
优先重载为成员函数,前置返回引用(支持链式),后置返回值(带 int 占位符);
遵循 "前置先改后返,后置先返后改" 的语义,符合用户对 ++ 的直觉;
递减运算符重载逻辑与递增完全一致,仅修改数值操作。