C++学习笔记(二十)——类之运算符重载
一、 运算符重载
作用:
运算符重载(Operator Overloading) 允许我们为自定义类赋予运算符(+ - * / == != [] ()
等)的特殊功能,使其像内置数据类型一样操作对象。
特点:
- 提高代码可读性,使类的对象能够像内置类型一样使用运算符。
- 可以定义新的行为,如两个
Complex
类对象的相加 (c1 + c2
)。 - 不能创建新的运算符,只能重载已有运算符。
- 部分运算符必须作为成员函数或友元函数。
二、基本语法和重载的运算符
(1)基本语法
返回类型 operator运算符 (参数) {
// 重载实现
}
- 返回类型:通常返回当前类的对象(支持链式调用)。
operator
关键字:用于声明或定义运算符重载。- 参数:一元运算符通常无参数,二元运算符有一个参数(通常为同类型对象)。
(2)推荐重载的运算符
运算符 | 作用 |
---|---|
+ - * / | 算术运算 |
++ -- | 自增/自减 |
>> << | 输入/输出 |
== != < > | 逻辑比较 |
[] | 数组访问 |
() | 仿函数 |
(3)不能重载的运算符
C++ 不能重载以下运算符:
.
成员访问.*
成员指针访问::
作用域解析sizeof
求大小typeid
获取类型
三、重载 +
运算符(成员函数)
作用:
+
运算符可以用于算术运算。
示例 ——重载 +
实现两个 Complex
对象相加:
#include <iostream>
using namespace std;
class Complex {
private:
double real, imag;
public:
Complex(double r = 0, double i = 0) : real(r), imag(i) {}
// 重载 + 运算符
Complex operator+(const Complex& other)
{
return Complex(real + other.real, imag + other.imag);
}
// 显示函数
void display()
{
cout << real << " + " << imag << "i" << endl;
}
};
int main() {
Complex c1(3, 4), c2(1, 2);
Complex c3 = c1 + c2; // 等价于 c1.operator+(c2)
c3.display(); // 输出:4 + 6i
system("pause");
return 0;
}
注意:
operator+
重载+
号,返回新的Complex
对象。c1 + c2
等价于c1.operator+(c2)
。
四、重载 ++
运算符(成员函数)
作用:
运算符 | 语法 | 特点 |
---|---|---|
前置递增 | ++obj | 先递增,再返回修改后的值 |
后置递增 | obj++ | 先返回当前值,再递增(带int 占位符) |
示例1 ——前置++
重载:
#include <iostream>
using namespace std;
class Counter {
private:
int value;
public:
Counter(int v = 0) : value(v) {}
// 前置递增:++obj
Counter& operator++()
{
++value; // 先增加值
return *this; // 返回当前对象
}
void show()
{
cout << "Value: " << value << endl;
}
};
int main() {
Counter c(5);
++c; // 先递增,再返回
c.show(); // 输出 Value: 6
system("pause");
return 0;
}
注意:
- 直接修改 value,然后返回当前对象的引用(
*this
)。 - 返回
Counter&
允许连续递增(如++++c;
)。
示例2 ——后置++
重载:
#include <iostream>
using namespace std;
class Counter {
private:
int value;
public:
Counter(int v = 0) : value(v) {}
// 后置递增:obj++
Counter operator++(int)
{
Counter temp = *this; // 先保存当前值
value++; // 再递增
return temp; // 返回原值的副本
}
void show()
{
cout << "Value: " << value << endl;
}
};
int main() {
Counter c(5);
Counter old = c++; // 先返回旧值,再递增
old.show(); // Value: 5 (旧值)
c.show(); // Value: 6 (递增后)
system("pause");
return 0;
}
注意:
operator++(int)
参数int
是占位符,无实际意义。- 返回
Counter
的副本,确保obj++
先返回原值,再递增。
五、重载 <<
运算符(友元函数)
作用:
由于 <<
运算符的左操作数是 ostream
类型,不能作为成员函数,因此需要定义友元函数。
(作为成员函数时,左操作数必须是 class 对象(obj),无法让cout
作为左操作数,即会出现obj << cout;
的情况)。
示例——重载 <<
实现 cout << Complex
:
#include <iostream>
using namespace std;
class Complex {
private:
double real, imag;
public:
Complex(double r = 0, double i = 0) : real(r), imag(i) {}
// 友元函数重载 <<
friend ostream& operator<<(ostream& out, const Complex& c)
{
out << c.real << " + " << c.imag << "i";
return out; // 允许链式调用
}
};
int main() {
Complex c1(5, 6);
cout << "复数: " << c1 << endl; // 调用 operator<<
system("pause");
return 0;
}
注意:
friend
关键字允许operator<<
访问Complex
的私有成员。- 必须返回
ostream&
,支持cout << c1 << c2;
链式调用。
六、重载 []
运算符
作用:
[]
运算符可以用于封装数组访问。
示例——重载 []
访问数组:
#include <iostream>
using namespace std;
class Array {
private:
int data[5];
public:
Array()
{
for (int i = 0; i < 5; i++)
data[i] = i * 10;
}
// 重载 []
int& operator[](int index)
{
if (index < 0 || index >= 5) {
cout << "索引超出范围!" << endl;
exit(1);
}
return data[index];
}
};
int main() {
Array arr;
cout << arr[2] << endl; // 输出 20
arr[2] = 99;
cout << arr[2] << endl; // 输出 99
system("pause");
return 0;
}
注意:
- 返回
int&
允许修改数组元素(支持arr[2] = 99
)。 - 防止越界访问,如果索引超出范围,直接
exit(1)
终止程序。
七、重载 ()
运算符
作用:
()
允许对象像函数一样被调用,用于仿函数(Function Object)。
示例——重载 ()
:
#include <iostream>
using namespace std;
class Multiply {
public:
int operator()(int a, int b)
{
return a * b;
}
};
int main() {
Multiply multiply;
cout << "3 × 4 = " << multiply(3, 4) << endl; // 输出 12
system("pause");
return 0;
}
注意:
operator()
允许对象multiply
像函数一样被调用。
八、重载 ==
运算符
作用:
==
运算符可以用于比较两个对象是否相同。
示例——重载 ==
比较 Person
是否相同:
#include <iostream>
using namespace std;
class Person {
private:
string name;
int age;
public:
Person(string n, int a) : name(n), age(a) {}
// 重载 ==
bool operator==(const Person& other)
{
return (name == other.name) && (age == other.age);
}
};
int main() {
Person p1("Alice", 25), p2("Alice", 25), p3("Bob", 30);
cout << (p1 == p2) << endl; // 输出 1(true)
cout << (p1 == p3) << endl; // 输出 0(false)
system("pause");
return 0;
}
注意:
operator==
比较name
和age
是否相同。