C++ 运算符重载详细介绍
C++ 运算符重载是指允许为用户定义的类型赋予运算符新的行为,从而使得自定义类型可以像内置类型一样使用运算符。通过运算符重载,可以提高代码的可读性和一致性。
一、运算符重载的基本规则
- 运算符重载的形式
- 运算符重载可以是成员函数或全局函数。
- 对于某些运算符,必须用成员函数实现(如
=
、[]
、()
、->
)。 - 对于对称运算符(如
+
、-
等),建议用全局函数实现。
- 不可重载的运算符
以下运算符无法重载:::
(作用域解析运算符).
(成员访问运算符).*
(成员指针访问运算符)sizeof
(类型大小运算符)typeid
(类型信息运算符)
- 返回值和参数
- 运算符的返回值类型和参数数量应尽量符合预期。
- 对于链式操作(如
+=
),建议返回引用。
二、使用成员函数重载的原因
- 访问类的私有和保护成员
- 成员函数可以直接访问类的私有和保护成员,因此重载运算符时无需额外设置。
- 适用于需要直接操作当前对象的运算符。
- 单目(unary)运算符
- 对于单目运算符(如
++
、--
、!
等),成员函数更直观,因为它们只作用于当前对象。
- 对于单目运算符(如
- 需要绑定左操作数为当前对象
- 如果运算符的左操作数必须是当前类的对象(如赋值运算符
=
),则必须用成员函数重载。 - 如
=
、[]
、()
和->
这些运算符只能用成员函数实现。
- 如果运算符的左操作数必须是当前类的对象(如赋值运算符
- 支持链式操作
- 某些运算符(如
=
和+=
)需要返回*this
的引用以支持链式操作。通过成员函数可以更方便地实现。
示例:重载=
运算符
- 某些运算符(如
class MyClass {
private:
int value;
public:
MyClass(int v = 0) : value(v) {
}
// 重载赋值运算符
MyClass& operator=(const MyClass& other) {
if (this != &other) {
value = other.value;
}
return *this;
}
};
三、使用全局函数重载的原因
- 对称性要求
- 对于二元运算符(如
+
、-
、*
等),全局函数能够保持左右操作数的对称性。 - 如果左操作数不是类的对象(如
3 + myObject
),则必须使用全局函数。
- 对于二元运算符(如
- 增强灵活性
- 全局函数可以使运算符作用于类的对象与非类的对象(如内置类型)的组合。
- 通过友元声明,仍然可以访问类的私有成员。
- 扩展性
- 全局函数可以更好地扩展已有类,而无需修改类的定义。
示例:重载+
运算符
- 全局函数可以更好地扩展已有类,而无需修改类的定义。
#include <iostream>
class MyClass {
private:
int value;
public:
MyClass(int v = 0) : value(v) {
}
// 友元声明
friend MyClass operator+(const MyClass& lhs, const MyClass& rhs);
void display() const {
std::cout << value << std::endl