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,一经查实,立即删除!

相关文章

ETL万岁

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

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

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

getter/setter_Getters / Setters。 邪恶。 期。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

计算机一级上机考试试题题库,2016年计算机一级上机考试题库

2016年计算机一级上机考试题库第1题、 ****** 本套题共有5小题 ******(1)新建文档WDA01.DOC&#xff0c;插入文档WTA01.DOC的内容&#xff0c;将文中所有“星星”替换为“行星”&#xff0c;存储为文档WDA01.DOC。(2)新建文档WDA02.DOC&#xff0c;插入文档WDA01.DOC的内容&…

stc单片机485发送多出一字节_单片机干货!STC8H案例制作分享(内含高清实物动图)...

本期&#xff0c;Lucy制作了九个案例分享给大家&#xff0c;分别为&#xff1a;流水灯、按键LED、数码管、点阵、定时蜂鸣器、NTC温度计、超声波测距仪、光敏RGB灯、氛围灯(红外)Lucy无偿提供全部案例的原理图和部分案例的代码。有需要的朋友先关注并私信我。需要源码私信我&am…

怎么调用获取被创建的预制体_Go 语言 Web 编程系列—— 获取用户请求数据(上)...

0、GET/POST 请求数据在 PHP 中&#xff0c;可以直接通过全局变量 $_GET 和 $_POST 快速获取 GET/POST 请求数据&#xff0c;GET 请求数据主要是 URL 查询字符串中包含的参数&#xff0c;以前面在线论坛项目的群组详情页为例&#xff1a;http://localhost:8080/thread/read?id…

删除表报正在使用_U盘拔出要不要点quot;安全删除USB硬件quot;退出?

小U盘&#xff0c;大用处。U盘不仅可以用来存储各种各样的文件&#xff0c;甚至还可以用来制作电脑启动盘、Win to Go系统盘等。直接拔还是点“安全删除”后再拔U盘呢&#xff1f;在用完U盘后&#xff0c;有的会点击电脑右下角“安全删除”才拔&#xff0c;有的则会不管那么多直…

职业规划测试软件,生涯规划常用测试工具

原标题&#xff1a;生涯规划常用测试工具认识自己测试生涯规划关于生涯规划的几个测试上周我们说到中学生很有必要进行生涯规划&#xff0c;在进行生涯规划前&#xff0c;我们需要对自己有一个更清晰、更全面的认识&#xff0c;随着心理学的发展&#xff0c;很多认识自我的测试…

使用SoapUI调用不同的安全WCF SOAP服务-基本身份验证,第一部分

在这个分为三部分的系列中&#xff0c;我将演示如何使用SoapUI API工具来调用安全的WCF SOAP服务。 第一篇文章将着重于创建将要测试的系统的服务。 第二篇文章将介绍在基本身份验证机制保护的情况下调用它所需的步骤。 在最后一部分中&#xff0c;我将对初始服务稍作更改&…

配置中文_星球大战:战机中队配置需求公布 支持中文

近日《星球大战》系列新作《星球大战&#xff1a;战机中队》公布&#xff0c;该作采用寒霜引擎打造&#xff0c;支持中文。游戏将于2020年10月3日发售&#xff0c;预购价格为238元&#xff0c;登陆Xbox One/PS4/PC(Steam/Origin/Epic)平台&#xff0c;有单人和多人模式&#xf…

为什么在生产中进行硒自动化测试对于您的下一个版本至关重要?

您是否认为仅仅是因为您的Web应用程序在过渡环境中以鲜艳的色彩通过了&#xff0c;您的生产环境也将是相同的吗&#xff1f; 您可能需要重新考虑&#xff01; 特别是&#xff0c;如果我们指的是跨浏览器测试 &#xff0c;则需要确保跨各种操作系统&#xff0c;运行在不同操作系…

手机usb共享计算机网络连接,如何将手机wifi网络通过USB共享给电脑?小编教你共享方法...

曾经就有过这样的情况&#xff0c;家里突然断网了&#xff0c;这时又需要打开电脑接收文件&#xff0c;或是需要在线编辑公众号的文章&#xff0c;着急得很&#xff0c;这时电脑没有网络怎么办呢&#xff1f;能不能使用手机的流量&#xff0c;来让电脑连网呢&#xff1f;有时候…

为全局变量赋值_实例分析如何远离漫天飞舞的全局变量

前篇《由static来谈谈模块封装》基本实现了对外隐藏属性&#xff0c;隐藏局部模块函数&#xff0c;开放接口的功能。对于这个话题还有些点没有深入探讨&#xff1a;为什么要这样做&#xff1f;以及这样做的好处。或许很多刚刚开始用C或者其他面向对象编程语言(比如C)的小伙伴们…