1.为什么要重载运算符?
通过重载运算符,可以将复杂的操作封装成简单的运算符形式,简化代码,提高可读性下面举一个简单的例子
计算两个点的坐标之和。
1.不重载运算符
#include <iostream>
using namespace std; class Point {
public:int x, y; // Point类的成员变量,表示点的x和y坐标// 构造函数,初始化x和y坐标Point(int x, int y) : x(x), y(y) {}// 成员函数,用于计算两个点的坐标之和并返回新的Point对象Point add(const Point& other) const {return Point(x + other.x, y + other.y); // 返回一个新Point,其坐标为当前对象和other对象坐标的和}
};int main() {Point p1(1, 2); // 创建一个Point对象p1,坐标为(1, 2)Point p2(3, 4); // 创建另一个Point对象p2,坐标为(3, 4)// 使用成员函数add来计算两个点的坐标之和,并将结果赋值给p3Point p3 = p1.add(p2);// 使用cout输出p3的坐标,格式为"(x, y)"cout << "The sum of p1 and p2 is: (" << p3.x << ", " << p3.y << ")" << endl;system("pause");return 0;
}
2.使用重载运算符
#include <iostream>
using namespace std; class Point {
public:int x, y; // 构造函数,用于初始化点的x和y坐标Point(int x, int y) : x(x), y(y) {}// 重载 "+" 运算符,使其能够用于Point类的对象// 这个函数接受一个Point对象作为参数,并返回一个新的Point对象// 新对象的坐标是原两个Point对象坐标的和Point operator+(const Point& other) const {return Point(x + other.x, y + other.y); // 返回一个新的Point对象,其坐标为当前对象和other对象坐标的和}
};int main() {Point p1(1, 2); // 创建一个Point对象p1,其坐标为(1, 2)Point p2(3, 4); // 创建另一个Point对象p2,其坐标为(3, 4)// 使用重载的 "+" 运算符来计算两个Point对象的坐标之和// 这行代码等价于调用 p1.add(p2),但由于运算符重载,我们可以直接使用 + 号Point p3 = p1 + p2;cout << "The sum of p1 and p2 is: (" << p3.x << ", " << p3.y << ")" << endl;system("pause");return 0;
}
重载运算符后可以使用+
来进行坐标点的运算,代码更加简洁,可读性更高
2.单目运算符
即只能对一个操作数进行操作
单目运算符的类型
单目递增与单目递减运算符
一个可以对日期进行递增和递减的操作,代码如下:
#include <iostream>
using namespace std;class Date {
private:int day;int month;int year;// 简化版的日期合法性检查void checkDate() {// 如果是2月28日,增加到3月1日if (month == 2 && day == 29) {day = 1;month = 3;}// 如果月份超过12,增加年份if (month > 12) {month = 1;year++;}}public:// 构造函数Date(int d, int m, int y) : day(d), month(m), year(y) {checkDate();}// 单目递增运算符重载Date& operator++() {day++;checkDate();return *this;}// 成员函数用于输出日期void diplayDate() const {cout << day << "/" << month << "/" << year;}
};int main() {Date today(28, 2, 2024); // 今天是2024年2月28日today.diplayDate(); // 使用成员函数输出日期cout << endl; // 输出换行++today; // 使用重载后的递增运算符today.diplayDate(); // 使用成员函数输出日期cout << endl; // 输出换行system("pause");return 0;
}
PS: 还可以使用后缀运算符,但如果只是想执行递增递减运算,应当选择前缀运算符。
因为在后缀运算符中,首先会复制当前对象,再对当前对象执行递增递减运算,最后返回复制对象,会多一步临时拷贝的步骤,且这个创建的临时拷贝也不会被使用
3.转换运算符
示例代码如下:
#include <iostream>
#include <sstream>
#include <string>
using namespace std;class Date {
private:int day;int month;int year;string dateInString; // 用于存储格式化后的日期字符串// 简化版的日期合法性检查void checkDate() {// 如果是2月28日,增加到3月1日(这里不考虑闰年)if (month == 2 && day == 29) {day = 1;month = 3;}// 如果月份超过12,增加年份if (month > 12) {month = 1;year++;}}public:// 构造函数,初始化日期并检查合法性Date(int d, int m, int y) : day(d), month(m), year(y) {checkDate();}// 单目递增运算符重载,将日期递增一天Date& operator++() {day++;checkDate();return *this;}// 类型转换运算符,将Date对象转换为const char*类型// 这样,Date对象可以直接被ostream类使用,如coutoperator const char* (){// 使用ostringstream将日期转换为字符串ostringstream oss;oss << month << "/" << day << "/" << year;// 将转换后的字符串存储在dateInString中dateInString = oss.str();// 返回字符串的C风格字符数组(const char*)return dateInString.c_str();}
};int main() {Date today(28, 2, 2024); // 使用类型转换运算符将Date对象转换为const char*,并使用cout输出cout << "Tomorrow's date: " << today << endl;system("pause");return 0;
}
通过类型转化后,可以使用cout
直接输出
4.双目运算符
可以对两个操作数进行操作的运算符
5.函数运算符operator()
函数运算符允许类的实例表现得就像函数一样,可以接受参数并返回结果
#include <iostream>
#include <string>class SimpleFunc {
public:// 重载()运算符,使其可以像函数一样被调用int operator()(int a, int b) {return a + b; // 这里我们简单地返回两个数的和}
};int main() {SimpleFunc func; // 创建SimpleFunc的实例// 使用SimpleFunc实例来计算两个数的和int result = func(3, 5); // 调用func对象,传入3和5作为参数// 输出结果std::cout << "The sum of 3 and 5 is: " << result << std::endl;system("pause");return 0;
}
6.移动构造函数和移动赋值运算符
移动构造函数和移动赋值运算符是性能优化功能,用于高性能编程,属于C++11标准的一部分,旨在避免复制不必要的临时值
移动构造函数: 移动构造函数是一个接受一个同类型对象的右值引用作为参数的构造函数。它的主要目的是在对象的构造过程中,将资源从另一个对象“移动”过来,而不是进行复制。
class MyClass {
public:MyClass(MyClass&& other) noexcept {//声明方法// 移动资源}
};
移动赋值运算符: 移动赋值运算符是一个接受一个同类型对象的右值引用作为参数的赋值运算符。它允许一个对象通过接管另一个对象的资源来改变其状态,而不是通过复制。
class MyClass {
public:MyClass& operator=(MyClass&& other) noexcept {//声明方法// 移动资源并赋值return *this;}
};