C++运算符重载
C++ 的运算符重载(Operator Overloading)是其强大扩展性的体现,它允许开发者赋予内置运算符(如 +, -, *, << 等)处理自定义类对象的能力。
1. 基本规则与限制
在开始编写代码前,必须牢记以下“死理”:
-
不能创建新运算符:你只能重载 C++ 语法中已有的运算符(例如不能造一个 表示幂运算)。
-
不改变优先级和结合性:
*的优先级永远高于+。 -
至少有一个参数是类类型:不能重载处理两个
int的运算符。 -
不可重载的运算符:
-
.(成员访问) -
.*(成员指针访问) -
::(域解析) -
?:(条件运算符) -
sizeof,typeid,alignof
-
2. 重载方式:成员函数 vs. 非成员函数
A. 成员函数重载
运算符作为类的成员。第一个操作数必须是该类的对象(由 this 指针隐式传递)。
C++
Complex operator+(const Complex& other) const {
return Complex(this->real + other.real, this->imag + other.imag);
}
B. 非成员函数(通常是友元)重载
如果左侧操作数不是该类的对象(例如 int + Complex 或 cout << Complex),则必须使用非成员函数。
C++
friend Complex operator+(double left, const Complex& right);
3. 分类知识点详解
3.1 算术运算符 (+, -, *, /)
通常返回一个新对象(传值返回)。建议先实现赋值运算符(如 +=),再用 += 实现 + 以减少代码冗余。
3.2 自增自减 (++, --)
分为前置和后置,通过一个占位参数 int 来区分:
-
前置:
Complex& operator++()(返回引用,效率高) -
后置:
Complex operator++(int)(返回原副本,效率低)
3.3 关系运算符 (==, !=, <, >)
必须返回 bool 类型。在 C++20 中,引入了 “三路比较运算符” <=>(太空船运算符),只需定义它,编译器就能自动生成所有关系运算。
3.4 赋值运算符 (=)
-
必须是成员函数。
-
默认赋值:编译器会生成浅拷贝赋值,如果类中有指针,必须手动重载以实现深拷贝。
-
准则:检查自赋值(
if (this == &other)),返回*this的引用。
3.5 流运算符 (<<, >>)
-
必须是非成员函数。因为第一个参数是
std::ostream&或std::istream&。
C++
std::ostream& operator<<(std::ostream& os, const Complex& c) {
os << c.real << " + " << c.imag << "i";
return os; // 支持链式调用
}
3.6 函数调用运算符 (())
重载后,类的对象可以像函数一样被调用,这种对象称为仿函数(Functor)。
C++
struct Linear {
double operator()(double x) { return a * x + b; }
double a, b;
};
4. 特殊运算符
-
下标运算符
[]:通常提供const和非const两个版本。 -
解引用运算符
*和->:常用于智能指针,必须返回指针或支持解引用的对象。 -
类型转换运算符:例如
operator bool(),允许对象直接用于条件判断。建议加上explicit防止意外隐式转换。
5. 最佳实践建议 (Checklist)
| 场景 | 推荐做法 |
| 一致性 | 含义应与内置类型保持一致(别让 + 做减法)。 |
| 返回类型 | 赋值运算(=, +=)返回引用;算术运算(+, -)返回新值。 |
| 对称性 | 如果 a + b 能行,那么 b + a 也应该能行(通常用非成员函数实现)。 |
| 效率 | 参数尽可能使用 const T& 以避免不必要的拷贝。 |
更多推荐

所有评论(0)