C++进阶之路:何为运算符重载、赋值运算符重载与前后置++重载(类与对象_中篇)

news/2024/9/19 18:24:57/ 标签: c++, 开发语言


✨✨ 欢迎大家来访Srlua的博文(づ ̄3 ̄)づ╭
~✨✨

🌟🌟 欢迎各位亲爱的读者,感谢你们抽出宝贵的时间来阅读我的文章。

我是Srlua小谢,在这里我会分享我的知识和经验。🎥

希望在这里,我们能一起探索IT世界的奥妙,提升我们的技能。🔮

记得先点赞👍后阅读哦~ 👏👏

📘📚 所属专栏:C/C++

欢迎访问我的主页:Srlua小谢 获取更多信息和资源。✨✨🌙🌙

​​​

​​​

 

目录

赋值运算符重载

运算符重载

赋值运算符重载

1. 赋值运算符重载格式

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

3. 用户没有显式实现时,编译器会生成一个默认赋值运算符重载,以值的方式逐字节拷贝。

前置++和后置++重载


赋值运算符重载

运算符重载

C++为了增强代码的可读性引入了运算符重载运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。

函数名字为:关键字operator后面接需要重载的运算符符号

函数原型:返回值类型 operator操作符(参数列表)

注意:

  • 不能通过连接其他符号来创建新的操作符:比如operator@

  • 重载操作符必须有一个类类型参数

  • 用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不能改变其含义

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

  • .*      ::     sizeof      ?:      . 注意以上5个运算符不能重载。这个经常在笔试选择题中出现。

#include <iostream>
using namespace std;// 全局的operator==
class Date
{
public:Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = 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;
}
void Test()
{Date d1(2018, 9, 26);Date d2(2018, 9, 27);cout << (d1 == d2) << endl;
}int main()
{Test();return 0;
}

class Date
{
public:Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}

bool operator==(Date* this, const Date& d2)
这里需要注意的是,左操作数是this,指向调用函数的对象

	bool operator==(const Date & d2){return _year == d2._year;&& _month == d2._month&& _day == d2._day;}
private:int _year;int _month;int _day;
};int main()
{Test();return 0;
}

赋值运算符重载

1. 赋值运算符重载格式

  • 参数类型:const T&,传递引用可以提高传参效率
  • 返回值类型:T&,返回引用可以提高返回的效率,有返回值目的是为了支持连续赋值
  • 检测是否自己给自己赋值
  • 返回*this :要复合连续赋值的含义
class Date
{
public:Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}Date(const Date& d){_year = d._year;_month = d._month;_day = d._day;}Date& operator=(const Date& d){if (this != &d){_year = d._year;_month = d._month;_day = d._day;}return *this;}
private:int _year;int _month;int _day;
};

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

class Date
{
public:Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}int _year;int _month;int _day;
};
// 赋值运算符重载成全局函数,注意重载成全局函数时没有this指针了,需要给两个参数
Date& operator=(Date& left, const Date& right)
{if (&left != &right){left._year = right._year;left._month = right._month;left._day = right._day;}return left;
}
// 编译失败:
// error C2801: “operator =”必须是非静态成员

原因:赋值运算符如果不显式实现,编译器会生成一个默认的。此时用户再在类外自己实现一个全局的赋值运算符重载,就和编译器在类中生成的默认赋值运算符重载冲突了,故赋值运算符重载只能是类的成员函数。

3. 用户没有显式实现时,编译器会生成一个默认赋值运算符重载,以值的方式逐字节拷贝

注意:内置类型成员变量是直接赋值的,而自定义类型成员变量需要调用对应类的赋值运算符重载完成赋值。

class Time
{
public:Time(){_hour = 1;_minute = 1;_second = 1;}Time& operator=(const Time& t){if (this != &t){_hour = t._hour;_minute = t._minute;_second = t._second;}return *this;}
private:int _hour;int _minute;int _second;
};
class Date
{
private:// 基本类型(内置类型)int _year = 1970;int _month = 1;int _day = 1;// 自定义类型Time _t;
};
int main()
{Date d1;Date d2;d1 = d2;return 0;
}

既然编译器生成的默认赋值运算符重载函数已经可以完成字节序的值拷贝了,还需要自己实现吗?

这里会发现下面的程序会崩溃掉?这里就需要我们深拷贝去解决。

#include <iostream>
using namespace std;
typedef int DataType;
class Stack
{
public:Stack(size_t capacity = 10){_array = (DataType*)malloc(capacity * sizeof(DataType));if (nullptr == _array){perror("malloc申请空间失败");return;}_size = 0;_capacity = capacity;}void Push(const DataType& data){// CheckCapacity();_array[_size] = data;_size++;}~Stack(){if (_array){free(_array);_array = nullptr;_capacity = 0;_size = 0;}}
private:DataType* _array;size_t _size;size_t _capacity;
};
int main()
{Stack s1;s1.Push(1);s1.Push(2);s1.Push(3);s1.Push(4);Stack s2;s2 = s1;return 0;
}

这段代码中的 Stack 类缺少拷贝构造函数和赋值运算符重载,因此在执行对象拷贝时会出现浅拷贝的问题,导致两个对象共享同一块内存。当其中一个对象析构时,另一个对象所指向的内存就会变成非法内存,从而导致程序崩溃。

要解决这个问题,可以手动实现深拷贝。具体来说,需要重载拷贝构造函数和赋值运算符,将原始对象中的数据复制到新对象中,并使用新的内存空间。

注意:如果类中未涉及到资源管理,赋值运算符是否实现都可以;一旦涉及到资源管理则必须要实现。

前置++和后置++重载

class Date
{
public:Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}// 前置++:返回+1之后的结果注意:this指向的对象函数结束后不会销毁,故以引用方式返回提高效率Date& operator++(){_day += 1;return *this;}// 后置++:// 前置++和后置++都是一元运算符,为了让前置++与后置++形成能正确重载// C++规定:后置++重载时多增加一个int类型的参数,但调用函数时该参数不用传递,编译器自动传递// 注意:后置++是先使用后+1,因此需要返回+1之前的旧值,故需在实现时需要先将this保存一份,然后给this + 1而temp是临时对象,因此只能以值的方式返回,不能返回引用Date operator++(int){Date temp(*this);_day += 1;return temp;}
private:int _year;int _month;int _day;
};
int main()
{Date d;Date d1(2022, 1, 13);d = d1++;    // d: 2022,1,13   d1:2022,1,14d = ++d1;    // d: 2022,1,15   d1:2022,1,15return 0;
}

​​​

希望对你有帮助!加油!

若您认为本文内容有益,请不吝赐予赞同并订阅,以便持续接收有价值的信息。衷心感谢您的关注和支持!


http://www.ppmy.cn/news/1463628.html

相关文章

掌握SQL注入检测:深入理解SQLMAP工具

引言 在网络安全领域&#xff0c;SQL注入是一个广泛存在的漏洞&#xff0c;它允许攻击者通过Web应用对数据库执行非法的SQL命令。SQLMAP是检测这类漏洞的顶尖工具之一。本文将深入探讨SQLMAP工具&#xff0c;从其基本介绍到高级使用技巧&#xff0c;帮助读者全面理解并有效运用…

Java基础入门day57

day57 JSP、Servlet&#xff0c;Java bean和JDBC整合项目 index.jsp页面 <% page contentType"text/html; charsetUTF-8" pageEncoding"UTF-8" %> <!DOCTYPE html> <html> <head><title>JSP - Hello World</title> …

Spring MVC的请求流程

Spring MVC&#xff08;Model-View-Controller&#xff09;是一种基于Java的实现了MVC设计模式的轻量级Web框架。它通过一套注解&#xff0c;可以快速地搭建一个可扩展、易维护的Web应用程序。下面是Spring MVC处理请求的基本流程&#xff1a; 用户发起请求&#xff1a;用户通过…

2024电激世界脉动-中国汽车品牌全球化制胜手册

来源&#xff1a;奥美Ogilvy&#xff1a; 近期历史回顾&#xff1a; 2024中国宏观经济专题报告-数据要素市场建设 2023-2024年度报告.pdf 2024制药与生化医疗技术产业链白皮书.pdf 从可再生能源到绿氢-中国投资助力埃及能源转型.pdf 2024有机旅行中国行业指引.pdf 2024中国技术…

Go源码--sync库(1)

简介 这篇主要介绍 sync.Once、sync.WaitGroup和sync.Mutex sync.Once once 顾名思义 只执行一次 废话不说 我们看源码 英文介绍直接略过了 感兴趣的建议读一读 获益匪浅 其结构体如下 Once 是一个严格只执行一次的object type Once struct {// 建议看下源码的注解&#xf…

Web组态可视化编辑器 快速绘制组态图

演示地址&#xff1a;by组态[web组态插件] 随着工业智能制造的发展&#xff0c;工业企业对设备可视化、远程运维的需求日趋强烈&#xff0c;传统的单机版组态软件已经不能满足越来越复杂的控制需求&#xff0c;那么实现Web组态可视化界面成为了主要的技术路径。 行业痛点 对于…

postman调用Grpc

环境&#xff1a; .net6.0 一、准备 安装nuget&#xff1a; Grpc.AspNetCore Google.Protobuf Grpc.Core.Api Grpc.Tools Grpc.AspNetCore.Server.Reflection Program.cs&#xff1a; public class Program{public static void Main(string[] args){var builder WebApplicat…

OpenCV Haar小波变换

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 图像Haar小波变换是一种基于小波分析的信号处理技术,特别适用于图像处理领域。以下是关于图像Haar小波变换过程: 分解:(1)假设原始图像为f(x,y),其中(x,y)表示图像上的像素坐标。 (2)对原始图像进行Haar小…

python web自动化(Pytest实战)

1.UnitTest框架与Pytest框架对⽐ 1&#xff09; unittest框架介绍 Unittest则是Python语⾔的标准单元测试框架。 Unittest⽀持⾃动化测试&#xff0c;测试⽤例的初 始化、关闭和测试⽤例的聚合等功能&#xff0c;它有⼀个很重要的特性&#xff…

瑞吉外卖项目学习笔记(一)

项目展示&#xff1a; 一、软件开发整体介绍 1.1 软件开发流程 作为软件开发人员&#xff0c;我们的主要工作是在 编码阶段 1.2 角色分工 1.3 软件环境 二、瑞吉外面项目介绍 2.1 项目介绍 系统管理后台页面&#xff1a; 移动端页面&#xff1a; 2.2 产品原型展示 产品原型是…

Python库之PyQuery的高级用法深度解析

Python库之PyQuery的高级用法深度解析 引言 PyQuery是一个强大的Python库&#xff0c;它提供了类似于jQuery的语法来解析和操作HTML和XML文档。虽然PyQuery的基本用法已经相当直观&#xff0c;但本文将深入探讨一些高级用法&#xff0c;帮助开发者更高效地处理复杂的HTML文档…

若依 ruoyi-vue SpringBoot聊天敏感词过滤sensitive-word

组件地址 https://github.com/houbb/sensitive-word 网上博客版本不是最新&#xff0c;查看官方文档&#xff0c;基于0.16.1整理总结&#xff0c;快速上手 pom文件引入 <dependency><groupId>com.github.houbb</groupId><artifactId>sensitive-word…

图像处理之计算物体的方向(C++)

图像处理之计算物体的方向&#xff08;C&#xff09; 文章目录 图像处理之计算物体的方向&#xff08;C&#xff09;前言一、PCA获取物体主要方向1.原理2.代码实现 二、Hu矩获取物体主要方向1.原理2.代码实现 总结 前言 在图像处理中&#xff0c;物体的方向&#xff08;倾斜角…

Python每秒1000次压测

Molotov是一个用Python编写的轻量级HTTP负载测试工具,旨在帮助开发者进行简单的性能测试和压力测试。它通过模拟大量并发用户访问来测试Web服务的响应时间、吞吐量以及稳定性。Molotov特别强调易用性和可扩展性,允许用户自定义场景和断言来更好地适应不同应用的测试需求。 安…

Docker拉取镜像报错:x509: certificate has expired or is not yet v..

太久没有使用docker进行镜像拉取&#xff0c;今天使用docker-compose拉取mongo发现报错&#xff08;如下图&#xff09;&#xff1a; 报错信息翻译&#xff1a;证书已过期或尚未有效。 解决办法&#xff1a; 1.一般都是证书问题或者系统时间问题导致&#xff0c;可以先执行 da…

深度学习模型在OCR中的可解释性问题与提升探讨

摘要&#xff1a; 随着深度学习技术在光学字符识别&#xff08;OCR&#xff09;领域的广泛应用&#xff0c;人们对深度学习模型的可解释性问题日益关注。本文将探讨OCR中深度学习模型的可解释性概念及其作用&#xff0c;以及如何提高可解释性&#xff0c;使其在实际应用中更可…

使用numpy手写一个神经网络

本文主要包含以下内容&#xff1a; 推导神经网络的误差反向传播过程使用numpy编写简单的神经网络&#xff0c;并使用iris数据集和california_housing数据集分别进行分类和回归任务&#xff0c;最终将训练过程可视化。 1. BP算法的推导过程 1.1 导入 前向传播和反向传播的总体…

Scala的简单认识

Scala编程基础 小白的Scala学习笔记 2024/5/21 上午某一时刻 文章目录 Scala编程基础spark是用Scala开发出来的Scala的优点 打开idea 搜索scala&#xff0c;安装 如果不小心点了取消&#xff0c;或者没有上图的提示&#xff0c;就在依赖里面添加 spark是用Scala开发出来的 类比…

Python中文件操作和异常处理

文章目录 一、文件操作1.概念2.文件3.二进制 二、基本文件操作三、乱码产生四、with open() as f五、代码实现文件复制粘贴六、try ... except ...七、代码比较 一、文件操作 1.概念 帮助我们把爬虫抓下来的数据&#xff0c;进行保存。 2.文件 在计算机中&#xff0c;没有p…

【荐闻】空中目标检测综述

https://t.zsxq.com/tgUjbhttps://t.zsxq.com/tgUjb 这篇综述论文全面回顾了空中目标检测的最新进展&#xff0c;包括五个不平衡问题、相关方法、实际应用和性能评估。以下是对论文内容的详细描述&#xff1a; 1&#xff09;引言&#xff1a;介绍了空中目标检测的概念&#x…