目录
1.运算符重载
2.1作用:
为了让C++的新类型:类。也可以进行内置类型的运算符操作。所以就有了运算符重载。
2.2定义:
运算符重载是具有特殊名字的函数,他的名字是由operator和后⾯要定义的运算符共同构成。和其 他函数⼀样,它也具有其返回类型和参数列表以及函数体。
这种函数一般直接在成员函数里面。和函数的格式一样,只不过函数名有要求:operator 运算符.
2.3特性:
1.重载运算符函数的参数个数和该运算符作⽤的运算对象数量⼀样多。⼀元运算符有⼀个参数,二元运算符有两个参数,二元运算符的左侧运算对象传给第⼀个参数,右侧运算对象传给第二个参数。
2.如果⼀个重载运算符函数是成员函数,则它的第⼀个运算对象默认传给隐式的this指针,因此运算 符重载作为成员函数时,参数⽐运算对象少⼀个。
3.运算符重载以后,其优先级和结合性与对应的内置类型运算符保持⼀致。
4.不能通过连接语法中没有的符号来创建新的操作符:⽐如operator@。
5.".* "(通过将成员函数设置为函数指针,在类外也可以访问成员函数)、
"::"(域作用限定符)、"sizeof"、"?:"(三目操作符)、"."(访问对象的成员)。
注意以上5个运算符不能重载。
6.重载操作符⾄少有⼀个 类 类型参数,不能通过运算符重载改变内置类型对象的含义。
如: operator+(int x, int y)。不行
7.⼀个类需要重载哪些运算符,是看哪些运算符重载后有意义。如:日期+日期,没有意义;日期-日期,有意义。
8.重载++运算符时,有前置++和后置++,运算符重载函数名都是operator++,⽆法很好的区分。 C++规定,后置++重载时,增加⼀个int形参,跟前置++构成函数重载,⽅便区分。
9.重载<<和>>时,需要重载为全局函数,因为重载为成员函数,this指针默认抢占了第⼀个形参位置,第⼀个形参位置是左侧运算对象,调⽤时就变成了对象<<cout,不符合使⽤习惯和可读性。 重载为全局函数把ostream/istream放到第⼀个形参位置就可以了,第⼆个形参位置当类类型对象。
2.4格式
从汇编可以看到,这二者没有任何区别。而隐式调用的逻辑,编译器帮我们加上operator了(前提是有对应运算符重载的声明和定义)。
2.5案例:
案例解析:
只是写法有所区别,别的都是对 '类和对象--中 ' 知识的运用。
Date.h
#pragma once
#include <iostream>
#include <assert.h>
using namespace std;
class Date {
public:
void Print();
Date(int year = 2024, int month = 11, int day = 22);
Date(const Date& d);
bool operator==(const Date& d);
private:
int _year = 0;
int _month = 0;
int _day = 0;
};
Date.cpp
#include "Date.h"
void Date::Print() {
cout << _year << '/' << _month << '/' << _day << endl;
}
Date::Date(int year, int month, int day) {
//cout << "Date()" << endl;
this->_year = year;
_month = month;
_day = day;
}
Date::Date(const Date& d) {
this->_year = d._year;
this->_month = d._month;
this->_day = d._day;
}
bool Date::operator==(const Date& d) {
if (_year == d._year) {
if (_month == d._month) {
return _day == d._day;
}
}
return false;
}
2.日期类
通过运算符重载,让自定义类型也能 比大小、+-*/、后置/前置++。
部分解析:
- Date+int
- Date-int
- 日期-日期
为了避免这样的问题,返回值需要修改。
Date.h
cpp
#pragma once
#include <iostream>
#include <assert.h>
using namespace std;
class Date {
// 友元函数声明
friend ostream& operator<<(ostream& out, const Date& d);
friend istream& operator>>(istream& in, Date& d);
public:
void Print();
Date(int year = 2024, int month = 11, int day = 22);
Date(const Date& d);
//----------------------------------------------------
// 比大小
bool operator==(const Date& d);
bool operator>(const Date& d);
bool operator<(const Date& d);
bool operator>=(const Date& d);
bool operator<=(const Date& d);
bool operator!=(const Date& d);
//----------------------------------------------------
// + -
//获取当月的天数
int GetMonthDay(int _year,int _month);
//日期+day
Date operator+(int day);
Date& operator+=(int day);
//日期-day
Date operator-(int day);
Date& operator-=(int day);
//日期-日期
int operator-(const Date& d);
//----------------------------------------------------
// 前置++和后置++
//前置++
Date& operator++();
//后置++
Date operator++(int);
Date& operator--();
Date operator--(int);
private:
int _year = 0;
int _month = 0;
int _day = 0;
};
// 重载 << 和 >>
//这里要访问成员变量。用的是友元
ostream& operator<<(ostream& out, const Date& d);
istream& operator>>(istream& in, Date& d);
Date.cpp
cpp
#include "Date.h"
void Date::Print() {
cout << _year << '/' << _month << '/' << _day << endl;
}
Date::Date(int year, int month, int day) {
//cout << "Date()" << endl;
this->_year = year;
_month = month;
_day = day;
}
Date::Date(const Date& d) {
this->_year = d._year;
this->_month = d._month;
this->_day = d._day;
}
//----------------------------------------------------
// 比大小
bool Date::operator==(const Date& d) {
if (_year == d._year) {
if (_month == d._month) {
return _day == d._day;
}
}
return false;
}
bool Date::operator>(const Date& d) {
if (this->_year > d._year) {
return true;
}
else if (this->_year == d._year) {
if (this->_month > d._month) {
return true;
}
else if(this->_month==d._month){
return _day > d._day;
}
}
return false;
}
bool Date::operator<(const Date& d) {
return !(*this >= d);
}
bool Date::operator>=(const Date& d) {
return (*this > d) || (*this == d);
}
bool Date::operator<=(const Date& d) {
return (*this < d) || (*this == d);
//return !(*this > d);
}
bool Date::operator!=(const Date& d) {
return !(*this == d);
}
//--------------------------------------------------------------
// + -
int Date::GetMonthDay(int _year, int _month) {
assert(_month > 0 && _month < 13);
assert(_year > 0);
static int a[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
//判断二月
if (_month == 2) {
if ((_year % 4 == 0 && _year % 100 != 0) || (_year % 400 == 0)) {
//是闰年,2月是29天
a[2] = 29;
}
}
return a[_month];
}
Date& Date::operator+=(int day) {
_day += day;
//不管走不走while,都需要获取当前月的天数
while (_day > GetMonthDay(_year, _month)) {
_day -= GetMonthDay(_year, _month);
++_month;
if (_month == 13) {
_month = 1;
++_year;
}
}
return *this;
}
Date Date::operator+(int day) {
Date tmp = *this;
tmp += day;
return tmp;
}
Date& Date::operator-=(int day) {
_day -= day;
//只有_day是<0,才需要获取上一个月的天数
while (_day <= 0) {
int last_month_day = GetMonthDay(_year, _month - 1);
_day += last_month_day;
--_month;
if (_month == 0) {
_month = 12;
--_year;
}
}
return *this;
}
Date Date::operator-(int day) {
Date tmp = *this;
tmp -= day;
return tmp;
}
int Date::operator-(const Date& d) {
//先找见日期小的那一个,然后一直++。
Date min = *this;
Date max = d;
int flag = 1;
if (min > max) {
min = d;
max = *this;
flag = -1;
}
//让小日期++
int gap = 0;
while (min != max) {
++gap;
++min;
}
return gap *flag;
}
//----------------------------------------------------------
// 前置++/后置++
Date& Date::operator++() {
return (*this += 1);
}
//后置++
Date Date::operator++(int) {
Date tmp = *this;
*this + 1;
return tmp;
}
Date& Date::operator--() {
return *this -= 1;
}
Date Date::operator--(int) {
Date tmp = *this;
tmp - 1;
return tmp;
}
//-----------------------------------------------------
// 重载 << 和 >>
ostream& operator<<(ostream& out, const Date& d) {
out << d._year << "年" << d._month << "月" << d._day << "日" << endl;
return out;
}
istream& operator>>(istream& in, Date& d) {
cout << "请依次输入年月日:>";
in >> d._year >> d._month >> d._day;
return in;
}