目录
一.运算符重载
1.1 概念
C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。
通俗的来说就是:内置类型(int,double),可以直接用各种运算符(=,+)
自定义类型,不能直接用各种运算符
为了自定义类型可以使用各种运算符,制定运算符重载的规则
函数名字为:关键字operator后面接需要重载的运算符符号。
函数原型:返回值类型 operator操作符(参数列表)
注意:
- 不能通过连接其他符号来创建新的操作符:比如operator@
- 重载操作符必须有一个类类型或者枚举类型的操作数
- 用于内置类型的操作符,其含义不能改变,例如:内置的整型+,不 能改变其含义
- .* 、:: 、sizeof 、?: 、. 注意以上5个运算符不能重载。
2.1 运算符重载的应用
用日期举例
#pragma once
#include <iostream>
#include <assert.h>
using std::cout;
using std::cin;
using std::endl;
class Date
{
public:
//判断是不是闰年
bool isLeapYear(int year) {
if ((year%4==0&&year%100!=0)||year%400==0)
{
return true;
}
else
{
return false;
}
}
// 获取某年某月的天数
int GetMonthDay(int year, int month);
// 全缺省的构造函数
Date(int year = 2000, int month = 1, int day = 2);
void Print() {
cout << _year << "-" << _month << "-" << _day << endl;
}
// 日期-日期 返回天数
int operator-(const Date& d);
// 日期+=天数
Date& operator+=(int day);
// 日期+天数
Date operator+(int day);
// 日期-天数
Date operator-(int day);
// 日期-=天数
Date& operator-=(int day);
// 前置++
Date& operator++() {
*this += 1;
return *this;
}
// 后置++
Date operator++(int) {
*this += 1;
return *this;
}
// 后置--
Date operator--(int) {
*this -= 1;
return *this;
}
// 前置--
Date& operator--() {
*this -= 1;
return *this;
}
// >运算符重载
bool operator>(const Date& d);
// ==运算符重载
bool operator==(const Date& d);
// >=运算符重载
bool operator >= (const Date& d) {
return *this == d || *this > d;
}
// <运算符重载
bool operator < (const Date& d) {
return !(*this > d || *this == d);
}
// <=运算符重载
bool operator <= (const Date& d) {
return !(*this > d);
}
// !=运算符重载
bool operator != (const Date& d) {
return !(*this == d);
}
private:
int _year;
int _month;
int _day;
};
#include "Date.h"
int Date:: GetMonthDay(int year, int month) {
assert(year > 0 && month > 0 && month < 13);//断言非法日期
static int monthDayArray[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
if (month == 2 && isLeapYear(year))
{
return 29;
}
else
{
return monthDayArray[month];
}
}
Date::Date(int year, int month, int day) {
if (year >= 1 &&
month <= 12 && month >= 1 &&
day >= 1 && day <= GetMonthDay(year, month))
{
_year = year;
_month = month;
_day = day;
}
else
{
cout << "日期非法" << endl;
}
}
2.1.1 单目操作符
单值操作数常用的有:++,--,+,- 等
注意:作为类成员的重载函数时,其形参看起来比操作数数目少1成员函数的操作符有一个默认的形参this,限定为第一个形参。
++
// 后置++
Date operator++(int) {//这里的int没有太多意思,就等于一个信号,让编译器理解这是后置++
Date tmp(*this);
*this += 1;
return tmp;
}
// 前置++
Date& operator++() {
*this += 1;
return *this;
}
--
// 后置--
Date operator--(int) {
Date tmp(*this);
*this -= 1;
return tmp;
}
// 前置--
Date& operator--() {
*this -= 1;
return *this;
}
+
Date Date:: operator+(int day) {
Date ret = (*this);
ret. _day += day;
//判断是否要进位
while (ret._day>GetMonthDay(ret._year,ret._month))
{
ret. _day -= GetMonthDay(ret._year, ret._month);
ret. _month++;
if (ret._month==13)
{
ret. _month = 1;
ret._year++;
}
}
return ret;//这种局部变量,不能用传引用返回
}
-
Date Date:: operator-(int day) {
if (day<0)
{
return *this + (-day);//复用+
}
Date ret = *this;
ret._day -= day;
while (ret._day<=0)
{
ret._month--;
if (ret._month==0)
{
ret._month = 12;
ret._year--;
}
ret._day += GetMonthDay(ret._year, ret._month);
}
return ret;
}
2.1.2关系操作符
注意:作为类成员的重载函数时,其形参看起来比操作数数目少1成员函数的操作符有一个默认的形参this,限定为第一个形参。
关系操作符有:>,<,==,>=,<=等
这里代码只需要实现>.和==代码,其他就可以复用了
>
bool Date:: operator>(const Date& d) {
if ((_year>d._year)
||(_year==d._year&&_month>d._month)||(_month==d._month&&_day>d._day))
{
return true;
}
else
{
return false;
}
}
==
bool Date:: operator==(const Date& d) {
return _year == d._year && _month == d._month
&& _day == d._day;
}
<
// <运算符重载
bool operator < (const Date& d) {
return !(*this > d || *this == d);
}
<=
// <=运算符重载
bool operator <= (const Date& d) {
return !(*this > d);
}
>=
// >=运算符重载
bool operator >= (const Date& d) {
return *this == d || *this > d;
}
!=
// !=运算符重载
bool operator != (const Date& d) {
return !(*this == d);
}
2.2赋值运算符重载
典型的赋值运算符:=,+=,-= 等。
=运算符重载是默认函数,不需要我们自己写,其他的需要我们自己写
但是有些注意:
当然也可以写出来,代码如下:
//=运算符重载
Date& operator =(const Date& d) { //用的引用减少拷贝构造
if (this != &d)//检查是否自己给自己赋值
{
_year = d._year;
_month = d._month;
_day = d._day;
}
return *this;//返回值
}
注意:这里只是浅拷贝,也就是值拷贝。
这里我们可以直接复用上面+和-的重载,写出+=和-=的重载函数
+=
Date& Date:: operator+=(int day) {
*this = *this + day; //复用+和=
return *this;
}
-=
Date& Date:: operator-=(int day) {
*this = *this - day; //复用-和=
return *this;
}
2.3日期的减法
日期减日期得到天数,日期加日期嗯没啥意思。
大致思路就是小的日期不断的++,直到跟大日期相等为止。
int Date:: operator-(const Date& d) {
int flaght = 1; //flaght判断是大-小,还是小-大。
Date max = *this;
Date min = d;
if (*this<d) //保证大日期的max,小日期是min
{
min = *this;
max = d;
flaght = -1;
}
int count = 0;
while (min!=max)
{
++count;//计数多少天相等
++min;//复用前置++
}
return count*flaght; //小-大是负数
}
3 总代码
#pragma once
#include <iostream>
#include <assert.h>
using std::cout;
using std::cin;
using std::endl;
class Date
{
public:
//判断是不是闰年
bool isLeapYear(int year) {
if ((year%4==0&&year%100!=0)||year%400==0)
{
return true;
}
else
{
return false;
}
}
// 获取某年某月的天数
int GetMonthDay(int year, int month);
// 全缺省的构造函数
Date(int year = 2000, int month = 1, int day = 2);
void Print() {
cout << _year << "-" << _month << "-" << _day << endl;
}
// 日期-日期 返回天数
int operator-(const Date& d);
// 日期+=天数
Date& operator+=(int day);
// 日期+天数
Date operator+(int day);
// 日期-天数
Date operator-(int day);
// 前置++
Date& operator++() {
*this += 1;
return *this;
}
// 后置++
Date operator++(int) {
Date tmp(*this);
*this += 1;
return tmp;
}
// 后置--
Date operator--(int) {
Date tmp(*this);
*this -= 1;
return tmp;
}
// 前置--
Date& operator--() {
*this -= 1;
return *this;
}
// >运算符重载
bool operator>(const Date& d);
// ==运算符重载
bool operator==(const Date& d);
// >=运算符重载
bool operator >= (const Date& d) {
return *this == d || *this > d;
}
// <运算符重载
bool operator < (const Date& d) {
return !(*this > d || *this == d);
}
// <=运算符重载
bool operator <= (const Date& d) {
return !(*this > d);
}
// !=运算符重载
bool operator != (const Date& d) {
return !(*this == d);
}
//=运算符重载
Date& operator =(const Date& d) { //用的引用减少拷贝构造
if (this != &d)//检查是否自己给自己赋值
{
_year = d._year;
_month = d._month;
_day = d._day;
}
return *this;//返回值
}
// 日期-=天数
Date& operator-=(int day);
private:
int _year;
int _month;
int _day;
};
#include "Date.h"
int Date:: GetMonthDay(int year, int month) {
assert(year > 0 && month > 0 && month < 13);
static int monthDayArray[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
if (month == 2 && isLeapYear(year))
{
return 29;
}
else
{
return monthDayArray[month];
}
}
Date::Date(int year, int month, int day) {
if (year >= 1 &&
month <= 12 && month >= 1 &&
day >= 1 && day <= GetMonthDay(year, month))
{
_year = year;
_month = month;
_day = day;
}
else
{
cout << "日期非法" << endl;
}
}
bool Date:: operator==(const Date& d) {
return _year == d._year && _month == d._month
&& _day == d._day;
}
bool Date:: operator>(const Date& d) {
if ((_year>d._year)
||(_year==d._year&&_month>d._month)||(_month==d._month&&_day>d._day))
{
return true;
}
else
{
return false;
}
}
Date Date:: operator+(int day) {
Date ret = (*this);
ret. _day += day;
//判断是否要进位
while (ret._day>GetMonthDay(ret._year,ret._month))
{
ret. _day -= GetMonthDay(ret._year, ret._month);
ret. _month++;
if (ret._month==13)
{
ret. _month = 1;
ret._year++;
}
}
return ret;
}
Date& Date:: operator+=(int day) {
*this = *this + day;
return *this;
}
Date Date:: operator-(int day) {
if (day<0)
{
return *this + (-day);//复用+
}
Date ret = *this;
ret._day -= day;
while (ret._day<=0)
{
ret._month--;
if (ret._month==0)
{
ret._month = 12;
ret._year--;
}
ret._day += GetMonthDay(ret._year, ret._month);
}
return ret;
}
Date& Date:: operator-=(int day) {
*this = *this - day;
return *this;
}
int Date:: operator-(const Date& d) {
int flaght = 1; //flaght判断是大-小,还是小-大。
Date max = *this;
Date min = d;
if (*this<d) //保证大日期的max,小日期是min
{
min = *this;
max = d;
flaght = -1;
}
int count = 0;
while (min!=max)
{
++count;//计数多少天相等
++min;
}
return count*flaght; //小-大是负数
}