[!NOTE]
以下内容为Chatgpt生成后整理
1. 基本概念
(1)什么是运算符重载?
运算符重载(Operator Overloading)允许我们为已有的运算符(如 +、-、*、== 等)定义新的行为,以便这些运算符能够处理我们自定义的类型(如类)。换句话说,运算符重载让运算符能够支持自定义类的对象,使得这些对象在运算符使用时像内置数据类型一样工作。
(2)为什么需要运算符重载?
运算符重载能够让我们:
- 提高代码的可读性和可维护性。
- 让自定义类的对象可以使用常见的运算符,方便直接参与运算。
例如,考虑两个 Complex 类对象相加,如果没有运算符重载,我们可能需要调用复杂的成员函数来完成加法操作,而运算符重载可以让加法操作变得简洁直观。
- C++ 允许重载的大部分运算符
- 不能重载的运算符:
::(作用域解析符)
.*(成员指针访问运算符)
.(成员访问运算符)
sizeof(求大小)
typeid(运行时类型识别)
2. 重载运算符的方式
- 作为成员函数(
operator+、operator== 等)
- 作为友元函数(
operator<<、operator>> 等)(1)作为成员函数
class 类名 { public: 返回类型 operator 运算符(参数列表) { } }; ```` ### (2)作为非成员函数(友元函数)
```cpp class 类名 { friend 返回类型 operator 运算符(参数列表); };
|
3. 常见运算符重载示例
(1) 重载 +(加法运算符)
1)为什么要重载 +?
默认情况下,C++ 仅支持内置类型的加法:
int a = 2, b = 3; int c = a + b;
|
但如果你定义了一个类,默认情况下 对象不能相加:
class Vector { public: int x, y; };
int main() { Vector v1{1, 2}, v2{3, 4}; Vector v3 = v1 + v2; }
|
📌 原因:
- C++ 不知道如何相加
v1 和 v2。
- 需要 重载
operator+,告诉 C++ 该怎么加。
2) operator+ 的基本语法
class ClassName { public: 返回类型 operator+(const ClassName& other) const { } };
|
📌 说明:
operator+ 必须是成员函数或友元函数。
const 保证不会修改原对象(推荐)。
other 是另一个参与相加的对象。
- 返回新对象,而不是修改
this。
3) 示例:为 Vector 类重载 +
假设 Vector 表示二维向量 (x, y),我们希望:
Vector v1(1, 2); Vector v2(3, 4); Vector v3 = v1 + v2;
|
我们可以这样实现:
#include <iostream> using namespace std;
class Vector { public: int x, y;
Vector(int x = 0, int y = 0) : x(x), y(y) {}
Vector operator+(const Vector& other) const { return Vector(x + other.x, y + other.y); }
void print() const { cout << "(" << x << ", " << y << ")" << endl; } };
int main() { Vector v1(1, 2), v2(3, 4); Vector v3 = v1 + v2; v3.print(); }
|
📌 关键点:
Vector(int x, int y) 构造函数 用于创建对象。
operator+ 返回一个新的 Vector,表示相加的结果。
- 不修改原对象,保持对象不可变性(
const)。
4) operator+ 的其他写法
(1)使用友元函数
如果 operator+ 需要访问 private 成员,就可以用友元函数:
class Vector { private: int x, y;
public: Vector(int x = 0, int y = 0) : x(x), y(y) {}
friend Vector operator+(const Vector& v1, const Vector& v2);
void print() const { cout << "(" << x << ", " << y << ")" << endl; } };
Vector operator+(const Vector& v1, const Vector& v2) { return Vector(v1.x + v2.x, v1.y + v2.y); }
int main() { Vector v1(1, 2), v2(3, 4); Vector v3 = v1 + v2; v3.print(); }
|
📌 区别:
- 友元函数 不是类的成员,但可以访问
private 成员。
- 适用于 操作两个不同类的对象(如
Matrix + Vector)。
(2)支持 += 运算
为了让 += 也能使用,我们可以重载 operator+=:
class Vector { public: int x, y;
Vector(int x = 0, int y = 0) : x(x), y(y) {}
Vector operator+(const Vector& other) const { return Vector(x + other.x, y + other.y); }
Vector& operator+=(const Vector& other) { x += other.x; y += other.y; return *this; } };
int main() { Vector v1(1, 2), v2(3, 4); v1 += v2; cout << v1.x << ", " << v1.y << endl; }
|
📌 区别:
operator+ 返回新对象,不修改 this。
operator+= 修改当前对象,返回 *this 以支持 链式调用。
(2) 重载 ==(比较运算符)
class Person { public: string name; int age;
Person(string name, int age) : name(name), age(age) {}
bool operator==(const Person& other) const { return (name == other.name && age == other.age); } };
int main() { Person p1("Alice", 25), p2("Alice", 25); if (p1 == p2) { cout << "相等" << endl; } else { cout << "不相等" << endl; } }
|
📌 注意:
(3) 重载 <<(流插入运算符,打印对象)
流插入运算符 << 不能作为类成员函数 (因为 cout 在左侧,不属于 Person 类),必须定义为友元函数:
#include <iostream> using namespace std;
class Person { public: string name; int age;
Person(string name, int age) : name(name), age(age) {}
friend ostream& operator<<(ostream& os, const Person& p) { os << "Name: " << p.name << ", Age: " << p.age; return os; } };
int main() { Person p("Alice", 25); cout << p << endl; }
|
📌 注意:
<< 必须返回 ostream&,否则 cout << p << "hello"; 不能连续输出。
(4) 重载 [](索引运算符)
如果你希望 obj[i] 访问对象内部数据,可以重载 operator[]:
#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) { return data[index]; } };
int main() { Array arr; cout << arr[2] << endl; arr[2] = 99; cout << arr[2] << endl; }
|
📌 注意:
operator[] 返回 int& 可以修改数组内容。
(5) 重载 ()(函数调用运算符)
1. 为什么要重载 ()?
通常,我们调用函数的方式如下:
int add(int a, int b) { return a + b; }
int main() { cout << add(2, 3); }
|
但如果你想创建一个行为类似函数的对象,可以重载 operator(),这样对象本身就能像函数一样使用:
class Adder { public: int operator()(int a, int b) { return a + b; } };
int main() { Adder add; cout << add(2, 3); }
|
这里 Adder 是一个对象,但它可以像函数一样调用!
2. 基本语法
class ClassName { public: 返回类型 operator()(参数列表) { } };
|
说明:
operator() 让对象变成 可调用对象,类似普通函数。
- 可以有 任意数量的参数。
- 可以有 返回值,与普通函数一样。
3. 代码示例
示例 1:最简单的 () 重载
#include <iostream> using namespace std;
class Multiply { public: int operator()(int a, int b) { return a * b; } };
int main() { Multiply multiply; cout << multiply(3, 4) << endl; }
|
📌 理解:
Multiply 类有一个 operator(),执行乘法。
multiply(3, 4) 看起来像函数调用,但 multiply 实际上是一个对象。
示例 2:用于 STL std::sort 的比较器
STL 算法(如 sort)经常使用 operator() 作为自定义排序规则:
#include <iostream> #include <vector> #include <algorithm> using namespace std;
class Compare { public: bool operator()(int a, int b) { return a > b; } };
int main() { vector<int> nums = {3, 1, 4, 1, 5, 9}; sort(nums.begin(), nums.end(), Compare());
for (int n : nums) cout << n << " "; }
|
📌 理解:
Compare 定义了 operator(),用于比较两个数的大小。
sort 不需要函数指针,而是直接传入 Compare() 对象。
示例 3:存储状态的函数对象
函数对象可以保存状态,而普通函数不能:
#include <iostream> using namespace std;
class Counter { private: int count; public: Counter() : count(0) {}
int operator()() { return ++count; } };
int main() { Counter counter; cout << counter() << endl; cout << counter() << endl; cout << counter() << endl; }
|
📌 理解:
Counter 对象记住了之前的 count 值,每次调用 () 都会递增 count。
- 普通函数不能存储状态,但函数对象可以!
示例 4:多参数版本
operator() 可以有多个参数:
class Power { public: double operator()(double base, int exponent) { double result = 1; while (exponent--) result *= base; return result; } };
int main() { Power power; cout << power(2, 3) << endl; }
|
📌 理解:
Power 计算 base^exponent。
- 多个参数 和普通函数一样!
4. operator() 的高级用法
(1) 作为 Lambda 表达式的替代
operator() 和 Lambda 很像,它可以代替 Lambda 表达式:
#include <iostream> #include <vector> #include <algorithm> using namespace std;
class LambdaLike { public: bool operator()(int x) { return x % 2 == 0; } };
int main() { vector<int> nums = {1, 2, 3, 4, 5, 6};
nums.erase(remove_if(nums.begin(), nums.end(), LambdaLike()), nums.end());
for (int n : nums) cout << n << " "; }
|
📌 理解:
LambdaLike 像 Lambda 一样,筛选偶数。
(2) 在 map 中用作自定义比较器
#include <iostream> #include <map> using namespace std;
class ReverseCompare { public: bool operator()(int a, int b) { return a > b; } };
int main() { map<int, string, ReverseCompare> myMap; myMap[3] = "Three"; myMap[1] = "One"; myMap[2] = "Two";
for (const auto& pair : myMap) { cout << pair.first << ": " << pair.second << endl; } }
|
📌 理解:
5. operator() 的总结
| 作用 |
适用场景 |
例子 |
| 让对象像函数一样调用 |
计算、操作类 |
Multiply multiply; multiply(2,3); |
| 作为 STL 自定义规则 |
sort()、map |
sort(v.begin(), v.end(), Compare()); |
| 代替 Lambda |
remove_if |
nums.erase(remove_if(nums.begin(), nums.end(), LambdaLike()), nums.end()); |
| 具有状态的可调用对象 |
记忆历史调用 |
Counter counter; counter(); |
(6) 重载 ->(箭头运算符)
如果你的类包含指针对象,可以重载 -> 使其像指针一样访问:
#include <iostream> using namespace std;
class PtrWrapper { private: int* ptr;
public: PtrWrapper(int val) { ptr = new int(val); } ~PtrWrapper() { delete ptr; }
int* operator->() { return ptr; } };
int main() { PtrWrapper p(42); cout << *(p.operator->()) << endl; }
|
📌 注意:
- 适用于 智能指针,如
std::unique_ptr<T>。
(7) 重载 =(赋值运算符)
必须处理深拷贝问题:
class String { private: char* data;
public: String(const char* str) { data = new char[strlen(str) + 1]; strcpy(data, str); }
~String() { delete[] data; }
String& operator=(const String& other) { if (this == &other) return *this; delete[] data; data = new char[strlen(other.data) + 1]; strcpy(data, other.data); return *this; } };
|
📌 注意:
总结
| 运算符 |
作用 |
典型应用 |
备注 |
operator+ |
加法 |
a + b |
返回新对象 |
operator- |
减法 |
a - b |
返回新对象 |
operator== |
比较 |
a == b |
返回 bool |
operator<< |
输出 |
cout << obj |
需要友元函数 |
operator[] |
索引 |
obj[i] |
允许修改数据 |
operator() |
函数调用 |
obj(x, y) |
仿函数 |
operator-> |
指针访问 |
obj->method() |
适用于指针包装类 |
operator= |
赋值 |
a = b |
处理深拷贝 |