C++类与对象(中)第二篇

前言:

C语言中使用运算符是对内置类型的数据进行操作,但是在C++中有了对象,导致对象无法通过运算符进行运算,故引入了运算符重载即需要重新定义这些运算符,赋予已有运算符新的功能,使它能够用于特定类型执行特定的操作;运算符重载就是对已有的运算符重新进行定义而且不能改变它本来的寓意,以达到适应不同的数据类型

运算符重载

class Date
{
private:int _year;int _month;int _day;
public://构造函数Date(int year=2023, int month=12, int day=20){_year = year;_month = month;_day = day;}
}
int main()
{Date d1(2023,12,20)Date d2(2000,10,20)return 0;
}

 定义了两个日期类对象d1,d2,如果想判断两个日期是否相同,需要比较各自的年、月、日,但是对象是自定义类型,运算符只支持内置类型的数据进行相关操作,此时我们需要重新定义运算符的规则,通过函数传参的形式可以对对象进行比较,但是函数名的命名可以千奇百怪,为规避命名不规则,增强代码的可读性,一律采用 operator运算符 同时也就实现自定义类型直接使用运算符

返回值类型  operator运算符(形参列表)
{....
}
采取成员函数的声明与定义相分离的方式,即类声明存放于Date.h文件中,成员函数的定义存放于Date.cpp文件中, 运算符重载为成员函数 ;一个类重载那些运算符呢?取决于运算符对于该类有没有实际意义;
// Date.h文件
class Date
{
private:int _year;int _month;int _day;
public://函数声明//d1==d2bool operator==(const Date& d);//显示对象信息void Print();
}
//Date.cpp文件//显示对象信息
void Date::Print()
{cout << _year << "-" << _month << "-" << _day << endl;
}
//d1==d2
bool Date::operator==(const Date& d)
{return _year == d._year&& _month == d._month&& _day == d._day;
}

!=运算符重载

对于类中的成员函数而言,第一个参数为隐藏的this指针;

重载双目运算符,只需要设置一个参数作为右操作数,而左操作数即为this指针指向的对象;

重载单目运算符,不必设置参数,操作数只有一个即为this指针指向的对象;

//d1 != d2
bool Date::operator!=(const Date& d)
{return !(*this == d);
}

>运算符重载

bool operator>(const Date& x, const Date& y)编译错误:参数太多,==运算符只有两个操作数;

运算符重载函数作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏的this;

//d1>d2
bool Date::operator>(const Date& d)
{if (_year > d._year){return true;}else if (_year == d._year&&_month > d._month){return true;}else if (_year == d._year&&_month == d._month&&_day > d._day){return true;}return false;
}

>=运算符重载

bool Date::operator>=(const Date& d)
{return (((*this) == d) || ((*this) > d));
}

<运算符重载

//d1<d2  注: 小于的对立面为大于等于;
bool Date::operator<(const Date& d)
{return !((*this) >= d);
}

<=运算符重载

//d1<=d2 注: 小于等于的对立面为大于;
bool Date::operator<=(const Date& d)
{return !((*this) > d);
}

=运算符重载

赋值运算符的重载格式:

  • 参数类型:const Date&,传递引用可以提高传参效率;
  • 返回值类型:Date&,返回引用可以提高返回的效率,有返回值目的是为了支持连续赋值;
  • 检测是否自己给自己赋值
  • 返回*this :要复合连续赋值的含义;

赋值运算符只能重载成类的成员函数不能重载成全局函数

原因:赋值运算符如果不显式实现,编译器会自动生成一个默认的赋值运算符重载以值的方式逐字节拷贝;此时用户再在类外自己实现一个全局的赋值运算符重载与编译器在类中生成的默认赋值运算符重载冲突,故赋值运算符重载只能是类的成员函数

//d1=d2
Date& Date::operator=(const Date& d)
{if (this != &d){_year = d._year;_month = d._month;_day = d._day;}return *this;
}

+=运算符重载

由于日期类对象的成员变量_month(月份)非固定,先获取每个月份的具体天数,然后实现日期+=函数的功能;

//获取每个月份的天数
int Date::GetMonthDay(int year, int month)
{assert(year >= 1 && (month <= 12 && month >= 1));int MonthArray[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))){return 29;}return MonthArray[month];
}
//日期+=天数
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 tmp(*this);tmp += day;return tmp;
}

-=运算符重载

//日期-=天数
Date& Date::operator-=(int day)
{if (day < 0){return *this += (-day);}_day -= day;while (_day <= 0){_month--;if (_month == 0){_year--;_month = 12;}_day += GetMonthDay(_year, _month);}return (*this);
}

-运算符重载

//日期-天数
Date Date::operator-(int day)
{Date tmp(*this);tmp -= day;return tmp;
}

前置++运算符重载

前置++:返回+1之后的结果;
注意:this指向的对象函数结束后不会销毁,故以引用方式返回提高效率;
//++d1 前置++无参
Date& Date::operator++()
{*this = *this + 1;return *this;
}

后置++运算符重载

前置++和后置++都是一元运算符,为了让前置++与后置++形成能正确重载,
C++规定 后置++重载时多增加一个int类型的参数,但调用函数时该参数不用传递,编译器自动传递;
注意:后置++是先使用后+1,因此需要返回+1之前的旧值,故需在实现时需要先将this保存
一份,然后给this+1 ,而temp是临时对象,因此只能以值的方式返回,不能返回引用;
//d1++
Date Date::operator++(int x)
{Date tmp(*this);*this += 1;return tmp;
}

 前置--运算符重载

//--d1
Date& Date::operator--()
{*this -= 1;return *this;
}

后置--运算符重载

//d1--
Date Date::operator--(int)
{Date tmp(*this);*this -= 1;return tmp;
}

-运算符重载

//d1-d2
int Date::operator-(const Date&d)
{//假设左大右小int flag = 1;Date max = *this;Date min = d;//假设错了,左小右大if (*this < d){max = d;min = *this;flag = -1;}int count = 0;//计数while (min != max){++min;++count;}return count * flag;
}

<<流插入运算符重载

流插入运算符为 “<<",与cout配合使用,其作用是支持内置类型的数值输出,若要使用cout,需要包含头文件#include<ostream>;

cout为ostream类的对象,cin为istream类的对象;

为了使自定义类型直接使用运算符,实现流插入运算符重载,<<流插入运算符是双目运算符,具有两个操作数,对于日期类,一个操作数为日期类对象,一个操作数为ostream类对象(cout) ,若在类中存放<<流插入运算符重载的声明,则形式如下:

void operator<<(ostream& out)//成员函数第一个参数为this指针,本质形式如下
//void operator<<(Date* const this,ostream& out)

当用户在主函数调用时cout<<d1时,导致编译出错;若调用d1<<cout,编译通过;

原因:成员函数第一个参数为隐藏的this指针,将<<流插入运算符的左操作数传递给this指针,所以调用d1<<cout,编译通过;

上述调用形式 d1<<cout会导致代码可读性太差,为保证逻辑自洽,将<<运算符重载为全局函数,但是涉及到成员变量私有问题,不能直接访问成员变量,采用友元函数解决此问题,将友元函数在类中声明;声明形式如下:

//Date.h
class Date
{
private:int _year;int _month;int _day;
public:friend ostream& operator<<(ostream& out,const Date&d)//友元函数的声明//...
}
//Date.cpp文件
ostream& operator<<(ostream& out, const Date& d)
{out << d._year << "年" << d._month << "月" << d._day << "日" << endl;return out;
}

>>流提取运算符重载

 流提取运算符重载的形式与流插入运算符重载实现类似,依然重载为全局函数,在类中声明为友元函数;

//Date.h
class Date
{
private:int _year;int _month;int _day;
public://友元函数的声明friend istream& operator>>(istream& in, Date& d);//...
}
istream& operator>>(istream& in, Date& d)
{in >> d._year >> d._month >> d._day;return in;
}

 运算符重载的注意事项:

  1. 不能通过连接其他符号(C++中不存在的运算符)来创建新的操作符:比如operator@;
  2. 重载操作符必须有一个类类型参数(因为运算符重载主要是为了让自定义类型能够像内置类型那样去使用运算符);
  3. 用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不能改变其含义(因为运算符重载主要是为了让自定义类型能够像内置类型那样去使用运算符,内置类型不需要运算符重载);
  4. 作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐 藏的this指针;
  5. .* :: sizeof ?: .  注意以上5个运算符不能重载

const成员函数

const修饰普通变量

const修饰普通变量的本质为定义了一个常量,形式如下:

Type const ValueName=value;
const Type valueName=value;

此时变量具有了常属性,变量里的数据只能被访问而且不能被修改,也就是意味着“只读”;

const修饰指针

const修饰指针变量本身,指针变量本身不允许被修改,即一旦得到了某个变量的地址,不能再指向其它变量;

int n = 20;
int* const p = &n; //const修饰指针变量本身

const修饰指针变量指向的内容,不可以通过指针修改其指向的变量的值,但是指针变量可以被修改;

int n = 10;
const int *p = &n;//const修饰指针变量指向的内容,即n=10;

const修饰函数形参

const修饰指针形参,形式如下:

void function(const Date* Var);

将外部实参的地址赋值给用const修饰的指针形参,用户无法通过指针修改其所指的外部实参,保护了数据的安全性;

void function(Date* const Var);

表示指针形参不会改变,用户依然可以通过指针修改传过来的外部实参,无法保证外部数据的安全性,const指针形参毫无意义;

 const修饰引用形参,形式如下:

void function(const Date& Var); //引用参数在函数内不可以改变

参数为引用,将外部实参传递给引用形参,传递的是外部实参本身,无需进行拷贝,增加了效率,同时参数是const引用,无法通过引用修改实参,保证了外部数据的安全性;

将const修饰的“成员函数”称之为const成员函数 const修饰类成员函数,实际修饰该成员函数 隐含的this指针 ,表明在该成员函数中 不能对类的任何成员进行修改;

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/339873.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

松下壁挂式新风系统推荐_松下壁挂式新风怎么样 松下壁挂式新风系统优势介绍【详解】...

现在很多的家庭都是会安装 新风系统 的&#xff0c;这样也是可以保证室内的空气质量的。其实市场上的新风系统品牌是比较多的&#xff0c;比如松下等&#xff0c;其质量是比较不错的&#xff0c;那么松下壁挂式新风系统的优势有哪些?我们来看看小编的相关介绍吧。松下壁挂式新…

ETL万岁

提取转换负载是用于从一个数据系统中提取数据并加载到另一个数据系统中的过程。 涉及的数据系统称为源系统和目标系统。 来自源系统的数据形状与目标系统不匹配&#xff0c;因此需要进行一些转换以使其兼容&#xff0c;该过程称为Transformation 。 转换是由map / filter / re…

云计算机内存不足怎么办,网易云音乐提示内存不足,电脑提示内存不足-

在有些时候我们的手机百度云提示内存不足了&#xff0c;这该怎么办呢?那么下面就由学习啦小编来给你们说说手机百度云提示内存不足的解决方法吧&#xff0c;希望可以帮到你们哦!手机百度云提示内存不足的解决方法一&#xff1a;手机用久了&#xff0c;需要安装杀毒软件&#x…

黑盒攻击的分类_「图像分类」图像分类中的对抗攻击是怎么回事?

欢迎大家来到图像分类专栏&#xff0c;深度学习分类模型虽然性能强大&#xff0c;但是也常常会因为受到小的干扰而性能崩溃&#xff0c;对抗攻击就是专门研究如何提高网络模型鲁棒性的方法&#xff0c;本文简要介绍相关内容。作者 | 郭冰洋编辑 | 言有三1 简介对于人类而言&…

getter/setter_Getters / Setters。 邪恶。 期。

getter/setter从2003年开始&#xff0c;艾伦霍鲁布&#xff08;Allen Holub&#xff09;讨论了为什么吸气和塞特方法是邪恶的著名文章&#xff0c;关于吸气/塞特方法是否是反模式&#xff0c;应该避免使用&#xff0c;还是我们在面向对象中不可避免地需要它&#xff0c;这是一个…

flowable画图教程_JeeGit企业级快速开发平台-JeeSite4 Flowable入门教程

注&#xff1a; 998元以下课程无咨询服务该课程包含服务内容&#xff1a;299元含发票在线课程观看权购课后&#xff0c;教学资源联系长春叭姐QQ&#xff1a;3211247533 索要教学内容3.1 第一章 业务流程 BPM、工作流引擎、Flowable、Activiti23.1.1 JeeSite4 Flowable 课程简介…

Java / Spring:如何快速生成整个Swagger记录的CRUD REST API

作为开发人员&#xff0c;我们在日常生活中经常面临的最繁琐的任务之一就是编写良好且易于理解的文档。 无论我们的文档只有几行来解释功能的核心功能&#xff0c;还是表明系统的来龙去脉的成熟文章都没关系。 重要的是&#xff0c;我们试图通过文档传达的信息是准确且可理解的…

计算机中的英语六级作文万能模板,大学英语六级作文万能模板7篇

很多人都觉得六级很难&#xff0c;其实主要是作文不会写&#xff0c;今天我们为大家整理了一些六级作文万能模板&#xff0c;大家可以借鉴一下&#xff0c;相信会对大家的提高有所帮助。大学英语六级作文万能模板1∶ 阐述主题型要求从一句话或一个主题出发&#xff0c;按照提纲…

中的实践 中兴_中兴通讯5G智慧治水业务在千岛湖畔下姜村成功实践

近日&#xff0c;中兴通讯智慧治水业务在千岛湖畔下姜村成功实践。这一业务为实现千岛湖下姜村水域的智能化管理、立体化监控提供了可靠保障&#xff0c;也将浙江电信5G网络、中兴通讯5G端到端解决方案在试商用实践中再推进一步。下姜村曾先后获得“全国创先争优先进基层党组织…

consul宕机配置丢失_简单的配置死机

consul宕机配置丢失编写整个框架的目的是为了处理应用程序的配置。 我更喜欢一种简单的方法。 如果通过配置来表示“ 部署之间可能有所不同的所有内容 ”&#xff0c;那么我们应该尝试使配置保持简单。 在Java中&#xff0c;最简单的选项是不起眼的属性文件。 属性文件的缺点是…

html post前md5加密,post提交及MD5加密

C# POST提交/// /// post 网址提交////// 提交网站/// 参数/// 编码方式///public static string PostWebRequest(string postUrl, string paramData, Encoding dataEncode){string ret string.Empty;try{byte[] byteArray dataEncode.GetBytes(paramData); //转化HttpWebReq…

一加7充电_一加真无线耳机曝光,65W快速充电器获认证

一加8系列发布后&#xff0c;曾有消息显示&#xff0c;一加旗下还有一款被称为一加Z的手机将于今年7月登陆市场。现在&#xff0c;距离传言中提到的发布时间越来越近&#xff0c;也再次有消息提到了这一时间点。不过&#xff0c;这次爆料中的新品并不是手机产品。来自爆料人士 …

从工作中清除代码–使用JUnit 5,Mockito和AssertJ编写可执行规范

可执行规范是可以用作设计规范的测试。 通过启用公共语言&#xff08;在DDD世界中&#xff0c;这也称为无处不在的语言 &#xff09;&#xff0c;它们使技术和业务团队能够进入同一页面。 它们充当代码的未来维护者的文档。 在本文中&#xff0c;我们将看到一种编写自动测试的…

怎么使用starwind部署iscsi_2019 年总结 - 多环境多版本的部署

自己几乎经历了部署演进的所有阶段&#xff0c;手动部署、自动部署&#xff0c;部署到服务器、部署到容器。我们也在不断演进并追赶行业前沿的技术/理念。保守估计今年可以基本追赶到行业前沿的最低水平。工作中经历了部署语言的多样化&#xff0c;部署目标的演化/进化&#xf…

家用计算机注意哪些参数,电脑小白买内存条要注意哪些?主要看哪些参数?这些知识要掌握...

内存条是电脑的核心硬件之一&#xff0c;它的作用主要是为CPU服务的&#xff0c;电脑运行的时候&#xff0c;CPU从硬盘里调用数据通过总线寻址放在内存里&#xff0c;内存相当于缓冲处理区&#xff0c;处理好信息后再回馈给CPU&#xff0c;然后电脑再根据指令运行。内存没有记忆…

java 单元测试技巧_其他一些单元测试技巧

java 单元测试技巧在我以前的文章中&#xff0c;我展示了有关JavaBeans单元测试的一些技巧。 在此博客文章中&#xff0c;我将针对单元测试一些相当常见的Java代码&#xff08;即实用程序类和Log4J日志记录语句&#xff09;提供另外两个提示。 测试实用程序类 如果您的实用程序…

日照职业技术学院计算机怎么样,日照职业技术学院宿舍条件怎么样 住宿环境好不好...

又到了一年一度的新生入学季&#xff0c;今年考上日照职业技术学院的学子们对你们的新学校有没有期待&#xff1f;下文中有途网小编给大家整理了日照职业技术学院的宿舍环境&#xff0c;供参考&#xff01;日照职业技术学院宿舍环境如何大学宿舍是各位同学们在大学期间会陪伴我…

cam350怎么看顶层_蛋糕胚速学教程大全,适合初学者看哦!

蛋糕胚速学教程大全&#xff0c;适合初学者看哦&#xff01;烘焙蛋糕最难的还是装饰&#xff0c;对手残星人来说&#xff0c;好不容易切好了蛋糕胚&#xff0c;抹面费了老大劲还是凹凸不平&#xff0c;做出来像狗狗啃过似的&#xff5e;快来看这份蛋糕抹面技巧&#xff0c;教你…

Java 14的新功能

2020年3月17日&#xff0c;Oracle发布了名为Java 14的Java新版本&#xff0c;其中包括许多新功能&#xff0c;工具&#xff0c;安全性&#xff0c;调试和更新的文档方面的改进。 但是&#xff0c;Oracle还向您提供Java的较旧版本&#xff0c;因为它具有向后兼容性&#xff0c;因…

计算机学校教学大纲,中等职业学校计算机应用基础教学大纲

附件4&#xff1a;中等职业学校计算机应用基础教学大纲一、课程性质与任务计算机应用基础课程是中等职业学校学生必修的一门公共基础课。本课程的任务是&#xff1a;使学生掌握必备的计算机应用基础知识和基本技能&#xff0c;培养学生应用计算机解决工作与生活中实际问题的能力…