运算符重载允许为自定义类型重新定义运算符行为,使对象操作更直观。通过operator关键字定义函数,如Complex operator+(const Complex& other)实现复数相加。必须遵守规则:不能创建新符号,部分运算符(如::、.、?:)不可重载,至少一个操作数为用户定义类型,不改变优先级和结合性。运算符可作为成员函数(左操作数为*this)或全局函数实现,后者常用于对称转换或流操作符,如friend std::ostream& operator

在C++中,运算符重载是一种允许我们为自定义类型(如类或结构体)重新定义已有运算符行为的机制。通过运算符重载,我们可以让对象像基本数据类型一样使用+、-、==等操作符,使代码更直观、易读。
运算符重载的基本语法
运算符重载本质上是函数重载的一种特殊形式,使用关键字 operator 加上要重载的符号来定义函数。
基本语法如下:
operator 运算符 (){
// 函数体
}
例如,重载加法运算符:
立即学习“C++免费学习笔记(深入)”;
class Complex {private:
double real, imag;
public:
Complex(double r = 0, double i = 0) : real(r), imag(i) {}
// 重载 + 运算符
Complex operator+(const Complex& other) const {
return Complex(real + other.real, imag + other.imag);
}
};
这样就可以写 a + b,其中 a 和 b 是 Complex 类型的对象。
运算符重载的规则
虽然C++提供了灵活的运算符重载能力,但必须遵守一些限制和规范:
- 只能重载C++已有的运算符,不能创建新的符号(比如定义 *** 或 @@)
- 以下运算符不能被重载:::(作用域解析)、.(成员访问)、.*(成员指针访问)、?:(三目条件)、sizeof、typeid、alignof、noexcept
- 重载运算符不能改变其优先级、结合性或操作数个数
- 至少有一个操作数必须是用户定义类型(防止对 int + int 这样的内置类型做重载)
- 可以作为类的成员函数或全局函数实现,部分运算符建议用特定方式实现(如 > 应作为友元或全局函数)
成员函数 vs 全局函数实现
运算符可以定义为类的成员函数,也可以定义为非成员的全局函数(常配合友元使用)。
成员函数方式:
- 左操作数隐式为 *this
- 适用于大多数二元运算符(如 +、-、*、/)和一元运算符(如 ++、--、!)
- 例如:
a + b调用的是 a.operator+(b)
全局函数方式:
- 两个操作数都显式传递
- 适合需要对称转换的情况(比如支持 1 + obj 和 obj + 1)
- 流操作符 > 必须用全局函数,因为左操作数是 std::ostream 或 std::istream
示例:重载输出运算符
// 声明友元以便访问私有成员class Complex {
friend std::ostream& operator };
std::ostream& operator os return os;
}
常见可重载运算符示例
以下是一些常用运算符的重载方式:
- 赋值运算符 =:通常需要手动定义深拷贝逻辑,避免浅拷贝问题
- 下标运算符 []:用于模拟数组访问,常返回引用以支持赋值
- 函数调用 ():定义仿函数(functor)
- 递增/递减 ++/--:区分前缀和后缀版本(后缀带一个 int 哑元参数)
- 关系运算符 ==、!=、:常用于排序或比较
后缀递增示例:
Complex operator++(int) { // 后缀形式Complex temp = *this;
real++;
imag++;
return temp; // 返回旧值
}
Complex& operator++() { // 前缀形式
real++;
imag++;
return *this; // 返回引用
}
基本上就这些。运算符重载提升了代码表达力,但也需谨慎使用,保持语义一致,避免滥用造成误解。











