赋值运算符重载

  • 1.为什么要用operator==而不是定义成一个函数
  • 2.赋值运算符重载在类里面使用
  • 3.赋值重载
  • 4.案例用赋值运算符写出一个日期运算的代码

如果我们想要类能和内置函数一样能比较大小怎么办
比如

#include<iostream>
using namespace std;class Date
{public:Date(int year, int month, int day){this->year = year;this->_month = month;this->_day = day;}private:int year;int _month;int _day;
};int main()
{Date d1(2022, 5, 18);Date d2(2021,5,16);if (d1 < d2){cout << "小于" << endl;}else{cout << "大于" << endl;}return 0;
}

这个代码其实是编译不过的,它不像内置类型一样能编译过,为什么?
因为内置类型是系统自己定义的,而自定义类型不同,因为这是自己定义,因为是自己定义的,所以系统没办法进行运算

那么编译器为了支持自定义类型可以使用各种运算符,所以就出了运算符重载

但是不要认为和函数重载是相同的,函数重载是函数名相同,参数不同,而运算符重载要解决的就是让自定义类型使用运算符
赋值运算符重载使用规则
函数原型:返回值类型 operator操作符(参数列表)
参数是运算符操作数
返回值是运算符运算后结果

使用演示

#include<iostream>
using namespace std;class Date
{public:Date(int year, int month, int day){_year = year;_month = month;_day = day;}
//private:int _year;int _month;int _day;
};bool operator==(Date& d1, Date& d2)
{return d1._year==d2._year&&d1._month==d2._month&&d1._day==d2._day;
}int main()
{Date d1(2022, 5, 18);Date d2(2022,5,18);if (operator==(d1, d2)){cout << "==" << endl;}return 0;
}

运行结果

看代码其实知道这代码是有点问题的,因为year这些成员变量是私有的所以不变成公有是编译不过去
但是是公有的话,那些我就没有办法有私有变量
那么怎么保证成员变量是私有的,我还能调用它
答案是类里面,不过因为写在类外面和类里面是有不同的,所以二个都讲

1.为什么要用operator==而不是定义成一个函数

在看完代码过后给一种感觉这不就是函数的调用吗?我不用operator==用成函数名不好吗?因为这是告许你可以这样用,但是这不是他真正的用法

可以看到这里把他重载了过后,能直接使用这个函数
其实这里就是编译器做了处理相当于

 if (d1==d2)//(operator==(d1, d2)){cout << "==" << endl;}

编译器会寻找它有没有重载,如果有重载就替换,如果没有就报错

2.赋值运算符重载在类里面使用

正确的使用方式

#include<iostream>
using namespace std;class Date
{public:Date(int year, int month, int day){_year = year;_month = month;_day = day;}bool operator==(const Date& d){return _year == d._year&& _month == d._month&& _day == d._day;}
private:int _year;int _month;int _day;
};int main()
{Date d1(2022, 5, 18);Date d2(2022,5,18);if (d1.operator==(d2)){cout << "==" << endl;}if (d1 == d2){cout << "==" << endl;}return 0;
}
 bool operator==(const Date& d){return _year == d._year&& _month == d._month&& _day == d._day;}

上面函数为什么只调用一个参数,是因为阴藏的this指针,如果上面写二个参数那总共加起来就是三个参数了
为什么加引用,因为不加上引用就会调用拷贝构造函数了

来个好玩的,下面代码会编译错误吗?如果没有调用的是那个函数

#include<iostream>
using namespace std;class Date
{public:Date(int year, int month, int day){_year = year;_month = month;_day = day;}bool operator==(Date d){return _year == d._year&& _month == d._month&& _day == d._day;}
//private:int _year;int _month;int _day;
};bool operator==(const Date& d1,const Date& d2)
{return d1._year == d2._year&& d1._month == d2._month&& d1._day == d2._day;
}int main()
{Date d1(2022, 5, 18);Date d2(2022,5,18);
if (d1.operator==(d2))
{cout << "==" << endl;
}if (d1 == d2){cout << "==" << endl;}return 0;
}

这里是没编译错误的,因为没有违反语法规定,但是调用那个就很好玩了,

 if (d1.operator==(d2)){cout << "==" << endl;}

这个肯定是调用类的,因为指定了

 if (d1 == d2){cout << "==" << endl;}

这个其实也是一样的,先去类找,类找不到就调用全局的函数
注意:
不能通过连接其他符号来创建新的操作符:比如operator@
重载操作符必须有一个类类型或者枚举类型的操作数
// 这里d2调用的默认拷贝构造完成拷贝,d2和d1的值也是一样的。
注意:
1.不能通过连接其他符号来创建新的操作符:比如operator@

2.重载操作符必须有一个类类型或者枚举类型的操作数

3.用于内置类型的操作符,其含义不能改变,例如:内置的整型+,不 能改变其含义

4.作为类成员的重载函数时,其形参看起来比操作数数目少1成员函数的
操作符有一个默认的形参this,限定为第一个形参.* 、:: 、sizeof 、?: 、. 注意以上5个运算符不能重载。这个经常在笔试选择题中出现。

3.赋值重载

代码

#include<iostream>
using namespace std;class Date
{public:Date(int year, int month, int day){_year = year;_month = month;_day = day;}void operator=(const Date& d){_year = d._year;_month = d._month;_day = d._day;}
private:int _year;int _month;int _day;
};int main()
{Date d1(2022, 5, 18);Date d2(2022,5,19);Date d3(d1);//拷贝构造  一个存在的对象去初始化未创建的对象d2 = d1;//赋值重载/赋值拷贝  二个存在的对象之间return 0;
}

运行结果

不过当然这个不完整的,因为c语言里面的的赋值是支持连等的
而我们这个没有因为没有返回值
所以改造如下

#include<iostream>
using namespace std;class Date
{public:Date(int year, int month, int day){_year = year;_month = month;_day = day;}Date operator=(const Date& d){_year = d._year;_month = d._month;_day = d._day;return *this;}//默认生成的析构函数,内置类型成员不做处理,自定义类型做处理Date(int year = 1, int month = 1, int day = 1);
private:int _year;int _month;int _day;
};int main()
{Date d1(2022, 5, 18);Date d2(2022,5,19);Date d3(d2);//拷贝构造  一个存在的对象去初始化未创建的对象d2 = d1;//赋值重载/赋值拷贝  二个存在的对象之间d3 = d2 = d1;return 0;
}

运行结果

4.案例用赋值运算符写出一个日期运算的代码

要求:写出一个日期函数,这个日期函数可以加减天数,并得到加减天数后的日期,或者是日期加减日期获得的天数

建一个头文件Date.h,和一个Date.cpp的文件,加主函数
代码

#include<iostream>
#include<assert.h>
using std::cout;
using std::cin;
using std::endl;class Date
{public:bool isLeadyear(int year){return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);}int GetMonthDay(int year, int month);void print(){cout << _year << "-" << _month << "-" << _day << endl;}private:int _year;int _month;int _day;};

因为是日期函数,所以会有三个成员变量年,月,日,而写日期运算有个问题
,就是怎么判断现在这个月有几天,所以我用GetMonthDay来计算,而因为二月会因为闰年的问题会多上1天,或者少上一天,所以我写了isLeadyear来计算闰年
这时候我们来到Date.cpp来完成接下来的代码

int Date::GetMonthDay(int year, int month)
{assert(year >= 0 && month > 0 && month < 13);const static int monthDayArray[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };if (month == 2 && isLeadyear(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 << "error" << endl;}
}

接下来就用赋值运算符来完成日期的运算了
因为赋值运算是可以复用的,所以只要写出一部分其他的都可以用

头文件
因为在类里面算内联,所以有些只有几行的我会放在类里面

#include<iostream>
#include<assert.h>
using std::cout;
using std::cin;
using std::endl;class Date
{public:bool isLeadyear(int year){return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);}int GetMonthDay(int year, int month);//默认生成的析构函数,内置类型成员不做处理,自定义类型做处理Date(int year = 1, int month = 1, int day = 1);void print(){cout << _year << "-" << _month << "-" << _day << endl;}// d1 - d2int operator-(const Date& d);Date operator+(int day);Date& operator+=(int day);Date operator-(int day);Date& operator-=(int day);bool operator<(const Date& d);bool operator==(const Date& 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);}bool operator>=(const Date& d){return !(*this <= d);}private:int _year;int _month;int _day;};

Date 函数

#include"Date.h"int Date::GetMonthDay(int year, int month)
{assert(year >= 0 && month > 0 && month < 13);const static int monthDayArray[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };if (month == 2 && isLeadyear(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 << "error" << endl;}
}Date Date::operator+(int day)
{Date ret(*this);ret += day;return ret;
}Date& Date::operator+=(int day)
{if (day < 0){return *this -= -day;}_day += day;  while (_day > GetMonthDay(_year, _month)){_day -= GetMonthDay(_year, _month);_month++;if (_month == 13){_year++;_month = 1;}}return *this;
}Date& Date::operator-=(int day)
{if (day < 0){return *this += -day;}_day -= day;while (_day <= 0){--_month;if (_month == 0){_month = 12;--_year;}_day += GetMonthDay(_year, _month);}return *this;
}bool Date::operator<(const Date& d)
{if ((_year < d._year)|| (_year == d._year && _month < d._month)|| (_year == d._year && _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;}

这里其实有个问题,就是为什么先写+=复用+,而不是写+复用加等

来对比一下二边代码,我写的数字代表的是拷贝构造的次数,
加复用加等
可以看到加等因为是引用本身是不用拷贝构造,而加是必须二次构造的
需要调用二次拷贝构造
加等复用加
因为加要二次拷贝构造,而加等复用加,又是二次拷贝构造
所以加复用加等是比较好的,而减等和减也一样

接下来就到了
自身加加,因为没办法知道哪里是前置和后置,所以规定有参数的是后置
因为代码少我是放到类里面的

 Date& operator++()//前置{*this += 1;return *this;}Date operator++(int)//后置{Date tmp(*this);tmp += 1;return tmp;}Date& operator--()//前置{*this -= 1;return *this;}Date operator--(int)//后置{Date tmp(*this);tmp -= 1;return tmp;}

最后就到了运算的最后一步了,日期减日期的相差值
日期用了方法是算出最大的日期和最小的日期,然后通过加加小的日期来和大的日期相同,和它们的差值就是我们要的答案
不过也好有问题就是可能出现负数,因为会默认是第一个参数减第二个参数
但是有可能第二个参数会比第一个参数大,所以第二个比第一个大,flag=-1
最后返回的时候乘以flag
Date函数代码

#include"Date.h"int Date::GetMonthDay(int year, int month)
{assert(year >= 0 && month > 0 && month < 13);const static int monthDayArray[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };if (month == 2 && isLeadyear(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 << "error" << endl;}
}Date Date::operator+(int day)
{Date ret(*this);ret += day;return ret;
}Date& Date::operator+=(int day)
{if (day < 0){return *this -= -day;}_day += day;  while (_day > GetMonthDay(_year, _month)){_day -= GetMonthDay(_year, _month);_month++;if (_month == 13){_year++;_month = 1;}}return *this;
}Date Date::operator-(int day)
{Date ret(*this);ret -= day;return ret;
}
Date& Date::operator-=(int day)
{if (day < 0){return *this += -day;}_day -= day;while (_day <= 0){--_month;if (_month == 0){_month = 12;--_year;}_day += GetMonthDay(_year, _month);}return *this;
}bool Date::operator<(const Date& d)
{if ((_year < d._year)|| (_year == d._year && _month < d._month)|| (_year == d._year && _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;}int Date::operator-(const Date& d)
{int falg = 1;Date max = *this;Date min = d;if(*this<d){max = d;min = *this;falg = -1;}int n = 0;while (min!=max){++n;++min;//这里必须是前置++,因为后置++,不会加到自己身上}return n * falg;
}

头文件代码

#include<iostream>
#include<assert.h>
using std::cout;
using std::cin;
using std::endl;class Date
{public:bool isLeadyear(int year){return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);}int GetMonthDay(int year, int month);//默认生成的析构函数,内置类型成员不做处理,自定义类型做处理Date(int year = 1, int month = 1, int day = 1);void print(){cout << _year << "-" << _month << "-" << _day << endl;}Date& operator++()//前置{*this += 1;return *this;}Date operator++(int)//后置{Date tmp(*this);tmp += 1;return tmp;}Date& operator--()//前置{*this -= 1;return *this;}Date operator--(int)//后置{Date tmp(*this);tmp -= 1;return tmp;}// d1 - d2int operator-(const Date& d);Date operator+(int day);Date& operator+=(int day);Date operator-(int day);Date& operator-=(int day);bool operator<(const Date& d);bool operator==(const Date& 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);}bool operator>=(const Date& d){return !(*this <= d);}private:int _year;int _month;int _day;};

赋值运算符重载和日期运算代码相关推荐

  1. js日期加减一天_JS日期加减,日期运算代码

    这篇文章主要介绍了JS日期加减,日期运算代码,需要的朋友可以参考下 一.日期减去天数等于第二个日期 function cc(dd,dadd){ //可以加上错误处理 var a = new Date( ...

  2. C++ 拷贝构造 与 赋值运算符重载

    拷贝构造 当我们创建了一个对象时,想让它的内容和一个已经创建好的对象的内容相同,那么就必须用到拷贝构造.拷贝构造编译器也会自动生成,也是C++类中的6个默认函数之一. 拷贝构造函数格式类名(const ...

  3. C++:运算符重载与类的赋值运算符重载函数

    目录 章节知识架构 一.运算符重载 1. 运算符重载的基本概念 代码段1 2.关于运算符重载的重要语法细则 二.运算符重载在类中的使用 三.类的默认成员函数:=重载函数(赋值运算符重载) 1.自定义= ...

  4. C++ ——赋值运算符重载函数

    文章目录 前言 一.赋值运算符重载函数是什么? 二.细谈赋值运算符重载函数 2.1 参数列表 2.2 返回值 2.3调用时机 二.赋值运算符重载函数练习 前言 在介绍赋值运算符重载之前,我们先看一段代 ...

  5. 浅谈深浅拷贝问题(这里只针对拷贝构造函数和赋值运算符重载)和简易srting类模拟实现

    浅谈深浅拷贝问题(这里只针对拷贝构造函数和赋值运算符重载)和简易srting类模拟实现 文章目录 浅谈深浅拷贝问题(这里只针对拷贝构造函数和赋值运算符重载)和简易srting类模拟实现 一.什么是浅拷 ...

  6. C++类的赋值运算符“=”重载,以及深拷贝和浅拷贝

    C++类的赋值运算符"="重载,以及深拷贝和浅拷贝 在面向对象程序设计中,对象间的相互拷贝和赋值是经常进行的操作. 如果对象在申明的同时马上进行初始化操作,则称之为拷贝运算.例如: ...

  7. 类的默认成员函数、赋值运算符重载

    目录 1.类的6个默认成员函数 2.1 概念 2.1 概念 2.2 特性 3.析构函数 3.1 概念 3.2 特性 4. 拷贝构造函数 4.1 概念 4.2 特征 5.赋值运算符重载 5.1 运算符重 ...

  8. 【带你吃透C++】运算符重载(赋值运算符重载)原来是这么一回事

    look here 运算符重载 赋值运算符重载 细节总结: – the End – 运算符重载 C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,其目的就是让自定义类型可以 ...

  9. 派生类的赋值运算符重载【C++继承】

    派生类的赋值符重载 情况分析 父类和子类都使用系统默认提供的赋值运算符重载 父类自实现赋值运算符重载,子类使用系统默认提供的赋值运算符重载. 父类使用系统默认提供的赋值运算符重载,子类自实现赋值运算符 ...

最新文章

  1. Android系统信息获取 之九:TelephonyManager类
  2. CAS(Central Authentication Service)——windows上简单搭建及測试
  3. Ajxa验证用户和二级联动的实例(五)
  4. 如何将开源项目部分代码作为private放在github上?
  5. 基于DFS的拓扑排序算法实现
  6. STATA长面板数据分析
  7. k8s-scheduler调度规则
  8. 企业级WEB应用服务器TOMCAT
  9. 洛谷P4315 月下“毛景树”(树剖+线段树)
  10. 『杭电1869』六度分离
  11. Beta冲刺总结随笔
  12. 通过设置Weblogic设置线程数提高系统并发
  13. 杭电多校第七场 1011 Kejin Player HDU(6656)
  14. 3GPP向ITU提交5G候选技术提案 NB-IoT确定为5G候选技术组成部分
  15. 利用python获取自己的qq群成员信息!
  16. golua 又一个Lua VM的Go语音实现
  17. SAAS-HRM系统概述与搭建环境
  18. 第四章:WPF依赖/附加属性,数据绑定(一)
  19. supervisor 进程管家的安装及测试
  20. PSP - AlphaFold2 适配不同来源搜索的 MSA 接口

热门文章

  1. 使用jQuery, CSS, JSON 和ASP.NET打造一个新闻轮换控件
  2. CSS_浮动排版布局
  3. 欧拉公式-python程序-计算机仿真方法(入门级)
  4. 前端逻辑练习题+学习记录 不定期更新
  5. 飞思卡尔智能车摄像头上位机…
  6. linux创建用户张飞,Linux系统操作测试试题 部分
  7. 3.3.3 反相比例运算放大电路
  8. 这64所大学官方公布考研【专业课真题】可以直接下载!
  9. bedtools intersect用法详解
  10. 联考素描头像怎么才能画到高分?联考新手必看!