C++ 类和对象 赋值运算符重载
前言:
在上文我们知道数据类型分为自定义类型和内置类型,当我想用内置类型比较大小是非常容易的但是在C++中成员变量都是在类(自定义类型)里面的,那我想给类比较大小那该怎么办呢?这时候运算符重载就出现了
一 运算符重载概念:
允许用户为自定义类定义或重新定义运算符的行为,使这些类在使用运算符时表现得像内置数据类型一样,从而提高代码的可读性和简洁性。
1.2 运算符重载与函数重载的区别:
我第一次听到这两个重载都傻傻的分不清楚,以为是一个意思。其实他们的区别可大了
函数重载:
函数重载是指在同一作用域中有多个同名函数,但它们的参数列表(参数的类型和数量)不同。编译器通过参数列表来决定调用哪个函数。函数重载的目的是为了提高代码的可读性和灵活性,使同一操作可以应用于不同类型的参数。
运算符重载:
运算符重载允许我们为用户定义的类型(如类)定义或重新定义特定运算符(如 +、-、*、/ 等)的行为。运算符重载函数的名称为 operator
后跟运算符符号。尽管这些函数的返回类型和参数列表与普通函数类似,但它们的目的是使自定义类型能够使用像内置类型一样的运算符。
1.3 运算符特点:
1 定义运算符重载函数:运算符重载是通过定义特殊的成员函数或全局函数来实现的
2 运算符重载函数的返回类型:通常是运算符操作后的结果类型。
3 运算符重载函数的参数:根据运算符的类型,参数可以是一个或多个。
4 *
::
sizeof
?:
.
注意以上5个运算符不能重载
3.1 代码解析:
运算符重载成员函数代码示例:
//成员函数 运算符重载
class Date
{
public:int _x = 5;int _y = 4;int operator+(const Date& b){return this->_x + b._x + this->_y + b._y;}//错误写法//int operator+(const Date& a , const Date& b)/*{return a.x + b.x + a.y + b.y;}*/
};
int main()
{//成员函数 运算符重载Date d1;Date d2;int sum = d1 + d2;std::cout << "d1 d2总和:" << sum << std::endl;return 0;
}
错误写法分析:
因为它是Date类里面的成员函数 又因为成员函数会自带一个隐含的this指针所以成员函数版本的 operator+
只能有一个显式参数。如果需要两个参数,则应使用全局函数版本的运算符重载。
//全局函数 运算符重载
class Point
{
public://默认构造函数Point(){this->_x = 5;this->_y = 15;}
//private:int _x;int _y;
};
bool operator==(const Point& b, const Point& a)
{return (b._x == a._x) && (b._y == a._y);
}int main()
{Point f1;Point f2;int B = f1 == f2;std::cout << "1相同 0相否:" << B << std::endl;return 0;
}
全局函数的运算符重载是在类外部实现的,不属于任何类,因此没有 this
指针。全局函数可以通过参数访问所有操作数。
假如我把成员函数变成私有的话那在全局函数里面就找不到他们了所以想改变就只能把运算符变量改为成员函数或者用友元函数或getter方法。
二 赋值运算符重载概念:
赋值运算符重载用于定义对象之间的赋值操作,即如何将一个对象的值赋给另一个对象。赋值运算符是 =
,它在赋值时被调用。通常我们需要重载赋值运算符来处理深拷贝,以防止浅拷贝带来的问题。
2.1 赋值运算符重载和拷贝构造的区别:
通过赋值运算符重载的概念我们知道它主要的功能是将一个对象的值赋给另一个对象,而这和拷贝构造又非常相似,然而赋值运算符重载与运算符重载只有两字相差却又是不同的内容,这就让我很想知道他们之间的区别到底是什么,接下来让我们一起来解密吧!
概念:
1. 赋值运算符重载
定义对象之间的赋值操作,即如何将一个对象的值赋给另一个对象。
2. 运算符重载:
定义或重新定义自定义类型的运算符行为,使其与内置类型的运算符行为一致。
3. 拷贝构造:
创建一个新的对象,并将其初始化为现有对象的副本。
区别:
拷贝构造函数和赋值运算符重载的主要区别在于它们的使用场景和目的。拷贝构造函数在对象创建时用于初始化新对象,目的是创建一个新的副本。赋值运算符重载在对象已存在时用于赋值操作,目的是修改现有对象的状态,使其与另一个对象的状态相同。拷贝构造函数通常接收一个对同类对象的常引用,而赋值运算符重载通常返回对象的引用,并接收一个对同类对象的常引用作为参数。而运算符重载和赋值运算符重载也真是差了两个字而已,并没有什么区别。
2.1.0 代码解析:
//赋值运算符重载
class Date1
{
public://默认构造函数Date1(int year = 2005, int month = 5, int date = 25){this->_year = year;this->_month = month;this->_date = date;}//拷贝构造函数Date1(const Date1& other){this->_year = other._year;this->_month = other._month;this->_date= other._date;}//赋值运算符重载Date1 operator=(const Date1& d){this->_year = d._year;this->_month = d._month;this->_date = d._date;return *this;}//输出void print(){std::cout << _year << "-" << _month << "-" << _date << std::endl;}private:int _year;int _month;int _date;
};int main()
{//构造函数Date1 q1(2024 , 7 , 12);Date1 q2(2021 , 6 , 26);//拷贝构造Date1 q3(q2);//赋值运算符重载Date1 q4;q4 = q1;//输出q1.print();q2.print();q3.print();q4.print();return 0;
}
从上面代码可以知道q3是在被创建的时候就直接被调用拷贝构造初始化而q4是先定义好之后在被调用赋值运算符重载初始化的。
那既然赋值运算符重载就是对象之间的赋值那和C语言中的赋值整体意思还是一样的但就是赋值的对象变了,我不知道大家是否还记得在C语言中可以连续赋值,让我们来试试在C++中的赋值运算符重载是否也可以实现呢?
#include <iostream>
class Date
{
public:int _year, _month, _day;Date(int year = 2005, int month = 5, int day = 25){this->_year = year;this->_month = month;this->_day = day;}// 赋值运算符重载Date& operator=(const Date& d) {// 自赋值检查if (this != &d) { _year = d._year;_month = d._month;_day = d._day;}return *this; // 返回当前对象的引用}void Print(){std::cout << _year << "-" << _month << "-" << _day << std::endl;}
};int main() {Date d1(2023, 7, 10);Date d2;Date d3;// 链式赋值d3 = d2 = d1;d1.Print(); d2.Print(); d3.Print(); return 0;
}
输出:
虽然输出的结果确实是链式但是又有非常多的疑惑比如为什么要传*this 还有执行顺序是什么……
让我们详细的来解答一下:
首先d2传给隐函数this指针然后d1传给 Date& d那这时d1就是d的引用了,执行到下面就是判断成员变量的地址是否相同(最开始它们之间的地址还是不一样的)跳出循环之后就返回*this即d2的引用返回值类型 Date& (这个我之前一直没看到所以就很困惑)
2.2 默认赋值运算符重载:
编译器生成的默认赋值运算符重载也和默认构造函数中分自定义和内置类型那它与默认构造函数有什么区别,让我们一探究竟吧
内置类型:
概念:编译器生成的默认赋值运算符会直接逐字节拷贝内置类型成员变量的值。
代码演示:
//默认赋值运算符重载(内置类型)
class Date1
{
public://默认构造函数Date1(int year = 2005, int month = 5, int date = 25){this->_year = year;this->_month = month;this->_date = date;}void print(){std::cout << _year << "-" << _month << "-" << _date << std::endl;}private:int _year;int _month;int _date;
};int main()
{Date1 q1(2024 , 7 , 12);Date1 q5;q5 = q1;q5.print();return 0;
}
输出:
就如上图所示,我并没有写赋值运算符重载但是它却给我打印出和q1对象中的成员变量一样的值,所以我们可以得出结论编译器生成的默认赋值运算符会直接逐字节拷贝内置类型成员变量的值。俗称浅拷贝。
自定义类型:
代码演示:
//默认赋值运算符重载(自定义类型)
class Date2
{
public:// 赋值运算符重载Date2& operator=(const Date2& d){if (this != &d) { // 自我赋值检查_a = d._a;}return *this;}private:int _a = 10;
};class Date3
{
public:// 默认构造函数Date3(int year = 2005, int month = 5, int date = 25){this->_year = year;this->_month = month;this->date = date;}void print(){std::cout << _year << "-" << _month << "-" << _date << std::endl;}private:int _year;int _month;int _date;Date2 c; // 包含 Date2 类型的成员变量
};int main()
{Date3 q1(2024, 7, 12);Date3 q5;q5 = q1; // 使用编译器生成的默认赋值运算符q5.print();return 0;
}
输出:
如图所示编译器生成的默认赋值运算符会调用自定义类型的赋值运算符重载。
相关文章:

C++ 类和对象 赋值运算符重载
前言: 在上文我们知道数据类型分为自定义类型和内置类型,当我想用内置类型比较大小是非常容易的但是在C中成员变量都是在类(自定义类型)里面的,那我想给类比较大小那该怎么办呢?这时候运算符重载就出现了 一 运算符重载概念&…...
【Python实战因果推断】35_双重差分6
目录 Strict Exogeneity No Time Varying Confounders No Feedback No Carryover and No Lagged Dependent Variable Strict Exogeneity 严格的外生性假设是一个相当技术性的假设,通常用固定效应模型的残差来表示: 严格的异质性说明: 这…...

【HarmonyOS】关于官方推荐的组件级路由Navigation的心得体会
前言 最近因为之前的630版本有点忙,导致断更了几天,现在再补上。换换脑子。 目前内测系统的华为应用市场,各种顶级APP陆续都放出来beta版本了,大体上都完成了主流程的开发。欣欣向荣的气息。 学习思路 关于学习HarmonyOS的问题…...
Spring中事件监听器
实现ApplicationListener接口 Configuration public class A48 {public static void main(String[] args) {AnnotationConfigApplicationContext context new AnnotationConfigApplicationContext(A48.class);context.getBean(MyService.class).doBusiness();context.close()…...

案例|LabVIEW连接S7-1200PLC
附带: 写了好的参考文章: 通讯测试工具和博图仿真机的连接教程【内含图文完整过程软件使用】 解决博图V15 V16 V17 V18等高版本和低版本在同款PLC上不兼容的问题 目录 前言一、准备条件二、步骤1. HslCommunicationDemo问题1:连接失败?问题…...

正点原子STM32(基于HAL库)6
目录 TFTLCD(MCU 屏)实验TFTLCD 简介TFTLCD 简介液晶显示控制器FSMC 简介FSMC 关联寄存器简介 硬件设计程序设计FSMC 和SRAM 的HAL 库驱动程序流程图程序解析 下载验证 LTDC LCD(RGB 屏)实验RGBLCD<DC 简介RGBLCD 简介LTDC 简介…...
flutter Android端权限
flutter 中权限请求path_provider Android 6.0 - 10.0 (API level 23 - 29)Android 11 (API level 30)具体实现示例注意事项 在 Flutter 中使用 path_provider 插件获取除本应用外所有的 PDF 文件,对于不同的 Android 版本(从 Android 6.0 到 Android 14…...

ant design form动态增减表单项Form.List如何进行动态校验规则
项目需求: 在使用ant design form动态增减表单项Form.List时,Form.List中有多组表单项,一组中的最后一个表单项的校验规则是动态的,该组为最后一组时,最后一个表单项是非必填项,其他时候为必填项。假设动态…...

7.16做题总结
今日也是让我看到了繁神的ACM历程,确实,我觉得繁神的历程里面确实有一句很好 不想打算法竞赛了。这是因为有别的事情要做,不是因为我打不动。 不想打比赛凌晨两点才睡了。因为我会困。 不想在群里和高水平选手水群了,因…...

unity使用 MQTT复现plant simulate仿真
unity使用 MQTT复现plant simulate仿真 一、plant simulate端配置 1、plant simulate MQTT组件配置,该组件在类库的信息流类目下,端口不变,填写ip即可; 2、设备配置界面,在控件入口和出口处各挂一个脚本,…...

MATLAB激光通信和-积消息传递算法(Python图形模型算法)模拟调制
🎯要点 🎯概率论和图论数学形式和图结构 | 🎯数学形式、图结构和代码验证贝叶斯分类器算法:🖊多类型:朴素贝叶斯,求和朴素贝叶斯、高斯朴素贝叶斯、树增强贝叶斯、贝叶斯网络增强贝叶斯和半朴素…...

初识HTML
一 HTML HTML(Hyper Text Markup Language),超⽂本标记语⾔.超文本:⽐⽂本要强⼤.通过链接和交互式⽅式来组织和呈现信息的⽂本形式.不仅仅有⽂本,还可能包含图⽚,⾳频,或者⾃已经审阅过它的学者所加的评注、补充或脚注等等.标记语言:由标签构成的语⾔。 1.HTML代码是由“标签…...

基于Rspack实现大仓应用构建提效实践|得物技术
一、实践背景 随着项目的逐步迭代,代码量和依赖的逐渐增长,应用的构建速度逐步进入缓慢期。以目前所在团队的业务应用来看(使用webpack构建),应用整体构建耗时已经普遍偏高,影响日常开发测试的使用效率&am…...

什么是MOW,以bitget钱包为例
元描述:MOW凭借其富有创意的故事情节和广阔的潜力在Solana上脱颖而出。本文深入探讨了其独特的概念和光明的未来。 Mouse in a Cats World (MOW)是一个基于Solana区块链的创新meme项目,它重新构想了一个异想天开且赋予权力的故事。在这个奇幻的宇宙中&am…...

pytorch说明
深度学习中的重要概念: 激活函数: 激活函数的必要性:激活函数不是绝对必须的,但在深度学习中,它们几乎总是被使用。激活函数可以引入非线性,这使得神经网络能够学习更复杂的模式。 激活函数的位置&#x…...

AI语音机器人是否可以设计开放式问题
什么叫开放式提问? 是指提出比较概括、广泛、范围较大的问题,对回答的内容限制不严格,给对方充分自由发挥的余地。 试想一下,就算不是语音机器人,是一个真人销售,和客户沟通时提的问题是开放式的…...
ModuleNotFoundError: No module named
python脚本执行出现这个错误,检查是否安装了对应的模块,确认已经安装,执行还是出错 原因是我时在c程序中启动执行的python脚本,c程序执行是使用了sudo权限,此时会报错,而在shell中执行python(下…...

【操作系统】进程管理——用信号量机制解决问题,以生产者-消费者问题为例(个人笔记)
学习日期:2024.7.10 内容摘要:利用信号量机制解决几个经典问题模型 目录 引言 问题模型 生产者-消费者问题(经典) 多生产者-多消费者问题 吸烟者问题 读者写者问题(难点) 哲学家进餐问题࿰…...
算法刷题笔记 KMP字符串(C++实现,并给出了求next数组的独家简单理解方式)
文章目录 题目描述基本思路实现代码 题目描述 给定一个字符串S,以及一个模式串P,所有字符串中只包含大小写英文字母以及阿拉伯数字。模式串P在字符串S中多次作为子串出现。求出模式串P在字符串S中所有出现的位置的起始下标。 输入格式 第一行输入整数…...

SpringCloud架构师面试
一、微服务是什么 1、基本概念 微服务是一种架构风格(区别于单体架构、垂直架构、分布式架构、SOA架构),应用程序被划分为更小的、流程驱动的服务。 2、微服务的特征 轻量化:将复杂的系统或者服务进行纵向拆分,每个…...

19c补丁后oracle属主变化,导致不能识别磁盘组
补丁后服务器重启,数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后,存在与用户组权限相关的问题。具体表现为,Oracle 实例的运行用户(oracle)和集…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来
一、破局:PCB行业的时代之问 在数字经济蓬勃发展的浪潮中,PCB(印制电路板)作为 “电子产品之母”,其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透,PCB行业面临着前所未有的挑战与机遇。产品迭代…...
sqlserver 根据指定字符 解析拼接字符串
DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...
LeetCode - 199. 二叉树的右视图
题目 199. 二叉树的右视图 - 力扣(LeetCode) 思路 右视图是指从树的右侧看,对于每一层,只能看到该层最右边的节点。实现思路是: 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...

保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek
文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama(有网络的电脑)2.2.3 安装Ollama(无网络的电脑)2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...

使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...

C# 表达式和运算符(求值顺序)
求值顺序 表达式可以由许多嵌套的子表达式构成。子表达式的求值顺序可以使表达式的最终值发生 变化。 例如,已知表达式3*52,依照子表达式的求值顺序,有两种可能的结果,如图9-3所示。 如果乘法先执行,结果是17。如果5…...
Spring AI Chat Memory 实战指南:Local 与 JDBC 存储集成
一个面向 Java 开发者的 Sring-Ai 示例工程项目,该项目是一个 Spring AI 快速入门的样例工程项目,旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计,每个模块都专注于特定的功能领域,便于学习和…...

【Veristand】Veristand环境安装教程-Linux RT / Windows
首先声明,此教程是针对Simulink编译模型并导入Veristand中编写的,同时需要注意的是老用户编译可能用的是Veristand Model Framework,那个是历史版本,且NI不会再维护,新版本编译支持为VeriStand Model Generation Suppo…...

高效的后台管理系统——可进行二次开发
随着互联网技术的迅猛发展,企业的数字化管理变得愈加重要。后台管理系统作为数据存储与业务管理的核心,成为了现代企业不可或缺的一部分。今天我们要介绍的是一款名为 若依后台管理框架 的系统,它不仅支持跨平台应用,还能提供丰富…...