在 C++ 中,操作符重载允许你为自定义类型定义操作符的行为,使其可以像内置类型一样使用。通过定义operator
函数,你可以指定操作符如何处理对象。
基本语法
ReturnType operator Op(Parameters) {
// 实现
}
示例
- 加法操作符重载
#include <iostream>
class Point {
public:
int x, y;
Point(int x, int y) : x(x), y(y) {}
// 重载加法操作符
Point operator+(const Point& other) {
return Point(x + other.x, y + other.y);
}
};
int main() {
Point p1(1, 2);
Point p2(3, 4);
Point p3 = p1 + p2; // 使用重载的加法操作符
std::cout << "p3: (" << p3.x << ", " << p3.y << ")" << std::endl;
return 0;
}
输出如下:
- 输出流操作符重载
#include <iostream>
class Point {
public:
int x, y;
Point(int x, int y) : x(x), y(y) {}
// 重载输出流操作符
friend std::ostream& operator<<(std::ostream& os, const Point& p) {
os << "(" << p.x << ", " << p.y << ")";
return os;
}
};
int main() {
Point p(1, 2);
std::cout << p << std::endl; // 使用重载的输出流操作符
return 0;
}
输出如下:
注意事项
-
不能重载:某些操作符(如
.
、::*
、?:
)不能重载。 -
返回类型:可以返回值或引用,具体取决于需求。
-
友元函数:对于某些操作符,如输出流操作符,通常需要定义为友元函数。
补充(对返回引用的补充)
基本概念
-
引用是 C++ 中的一种别名,它允许你创建一个变量的别名。通过引用,你可以直接操作原始变量,而不必创建其副本。
-
返回引用是指在函数返回一个变量的引用,而不是返回其值。这在
C++
中是一个重要的概念,尤其在涉及到大对象或链式操作时,可以提高性能和效率。
int a = 5;
int& ref = a; // ref 是 a 的引用
ref = 10; // 修改 ref 实际上修改了 a
std::cout << a; // 输出 10
返回引用的示例详解
#include <iostream>
class Array {
public:
int arr[5]; // 存储5个整数的数组
Array() { // 构造函数,初始化数组
for (int i = 0; i < 5; ++i) {
arr[i] = i; // 将 arr[0] 到 arr[4] 初始化为 0 到 4
}
}
// 重载下标操作符,返回元素的引用
int& operator[](size_t index) {
return arr[index]; // 返回数组中某个元素的引用
}
};
int main() {
Array myArray;
// 通过返回引用直接修改数组元素
myArray[2] = 10;
// 输出修改后的数组
for (int i = 0; i < 5; ++i) {
std::cout << myArray[i] << " ";
}
std::cout << std::endl;
return 0;
}
返回引用的工作原理
-
重载下标操作符:
operator[]
被重载,使得我们可以使用myArray[i]
来访问arr
数组的元素。
int& operator[](size_t index)
返回arr[index]
的引用。 -
使用引用:
当你执行myArray[2] = 10;
时,实际上是修改arr
数组中第 2 个元素的值。
由于operator[]
返回的是引用,所以你直接在数组中修改值,而不是创建其副本。
返回引用的好处
- 避免复制:当返回对象的引用时,不会创建对象的副本,这可以节省内存和时间,尤其是对于大型对象。
- 允许链式操作:返回引用可以让你链式调用多个操作。
注意事项
- 确保引用有效:返回引用时要确保所引用的对象在使用期间是有效的。若引用一个局部变量的地址,则会导致未定义行为。
int& func() {
int temp = 5; // 临时变量
return temp; // 返回局部变量的引用(不安全)
}
上面的代码是错误的,因为 temp
在函数结束后被销毁。
- 避免返回临时对象的引用:临时对象在作用域结束后会被销毁,因此不应返回临时对象的引用。