编写派生的赋值运算符重载函数 编写派生的赋值运算符重载函数一、核心概念赋值运算符operator用于将一个已存在的对象赋值给另一个已存在的对象。在继承关系中派生类的赋值运算符需要负责赋值基类部分和派生类新增部分。二、赋值运算符 与 拷贝构造函数对比项拷贝构造函数赋值运算符调用时机创建新对象时已有对象赋值时目标对象不存在新创建已存在是否需要释放旧资源不需要可能需要语法Student b(a)或Student b ab a三、派生类赋值运算符的调用规则3.1 规则总结派生类赋值运算符调用规则 1. 派生类赋值运算符必须赋值基类部分 ↓ 2. 如果派生类没有定义赋值运算符编译器会自动生成 ↓ 3. 编译器生成的赋值运算符会自动调用基类的赋值运算符 ↓ 4. 如果派生类自定义了赋值运算符编译器不会自动调用基类版本 → 必须显式调用四、四种场景详细分析4.1 场景一基类和派生类都没有定义赋值运算符classPerson{int_idPerson;public:Person(intid1):_idPerson(id){}// 没有定义 operator → 编译器自动生成按位赋值};classStudent:publicPerson{int_snum;public:Student(intid1,ints1):Person(id),_snum(s){}// 没有定义 operator → 编译器自动生成// 编译器生成的赋值运算符会自动调用基类的赋值运算符};intmain(){Studentstuda(111111,22222);Studentstudb(333333,44444);studbstuda;// 使用编译器生成的赋值运算符return0;}编译器生成的代码概念上Studentoperator(constStudentother){if(this!other){Person::operator(other);// 自动调用基类赋值运算符_snumother._snum;// 按位赋值派生类成员}return*this;}4.2 场景二基类定义了赋值运算符派生类没有定义classPerson{private:int_idPerson;public:Person(intid1):_idPerson(id){}// 基类定义了赋值运算符Personoperator(constPersonper){if(this!per){_idPersonper._idPerson;}coutPerson::operatorendl;return*this;}};classStudent:publicPerson{private:int_snum;public:Student(intid1,ints1):Person(id),_snum(s){}// 没有定义 operator → 编译器自动生成// 编译器会自动调用基类的赋值运算符};intmain(){Studentstuda(111111,22222);Studentstudb(333333,44444);cout 赋值前 endl;studa.PrintStudent();studb.PrintStudent();studbstuda;// 调用编译器生成的赋值运算符cout\n 赋值后 endl;studa.PrintStudent();studb.PrintStudent();return0;}输出Person(int) Student(int, int) Person(int) Student(int, int) 赋值前 身份证号111111 学号22222 身份证号333333 学号44444 Person::operator ← 自动调用基类赋值运算符 赋值后 身份证号111111 学号22222 身份证号111111 学号222224.3 场景三基类和派生类都定义了赋值运算符正确做法classPerson{private:int_idPerson;public:Person(intid1):_idPerson(id){}Personoperator(constPersonper){if(this!per){_idPersonper._idPerson;}coutPerson::operatorendl;return*this;}};classStudent:publicPerson{private:int_snum;public:Student(intid1,ints1):Person(id),_snum(s){}// 正确显式调用基类赋值运算符Studentoperator(constStudentstud){if(this!stud){Person::operator(stud);// 关键调用基类赋值运算符_snumstud._snum;}coutStudent::operatorendl;return*this;}};intmain(){Studentstuda(111111,22222);Studentstudb(333333,44444);studbstuda;return0;}输出Person::operator ← 显式调用基类赋值运算符 Student::operator4.4 场景四派生类定义了赋值运算符但没有调用基类版本危险classPerson{private:int_idPerson;public:Person(intid1):_idPerson(id){}Personoperator(constPersonper){if(this!per){_idPersonper._idPerson;}coutPerson::operatorendl;return*this;}};classStudent:publicPerson{private:int_snum;public:Student(intid1,ints1):Person(id),_snum(s){}// 错误没有调用基类赋值运算符Studentoperator(constStudentstud){if(this!stud){// Person::operator(stud); // 遗漏了_snumstud._snum;}coutStudent::operatorendl;return*this;}};intmain(){Studentstuda(111111,22222);Studentstudb(333333,44444);studbstuda;// 问题studb 的基类部分_idPerson没有被赋值// studb._idPerson 仍然是 333333而不是 111111return0;}五、四种场景对比总结场景基类有 operator派生类有 operator派生类是否调用基类版本结果1编译器生成编译器生成自动调用正确2用户定义编译器生成自动调用正确3用户定义用户定义显式调用正确4用户定义用户定义未调用错误基类部分未赋值六、错误写法与正确写法对比6.1 错1忘记调用基类赋值运算符Studentoperator(constStudentstud){if(this!stud){// 忘记调用 Person::operator(stud)_snumstud._snum;}return*this;}// 问题基类成员没有被赋值6.2 错2无穷递归引起栈溢出Studentoperator(constStudentstud){if(this!stud){operator(stud);// 死递归调用的是自己_snumstud._snum;}return*this;}6.3 错3错误的类型转换Studentoperator(constStudentstud){if(this!stud){((Person*)this)-operator(stud);// 可以但不推荐_snumstud._snum;}return*this;}6.4 正确写法Studentoperator(constStudentstud){if(this!stud){Person::operator(stud);// 显式调用基类版本_snumstud._snum;}coutStudent::operatorendl;return*this;}七、关键要点总结要点说明必须调用基类赋值运算符派生类赋值运算符必须显式调用基类版本语法Person::operator(stud);不调用的后果基类成员不会被赋值导致对象状态不完整编译器自动生成如果派生类没有定义编译器会自动生成并调用基类版本与拷贝构造的区别拷贝构造自动调用基类版本赋值运算符需要显式调用自赋值检查必须先检查this ! other

相关新闻

最新新闻

浏览器资源嗅探革命:猫抓插件如何让你成为网页媒体管理专家

浏览器资源嗅探革命:猫抓插件如何让你成为网页媒体管理专家

浏览器资源嗅探革命:猫抓插件如何让你成为网页媒体管理专家 【免费下载链接】cat-catch 猫抓 浏览器资源嗅探扩展 / cat-catch Browser Resource Sniffing Extension 项目地址: https://gitcode.com/GitHub_Trending/ca/cat-catch 你是否曾遇到过这样的困扰&…

2026/7/13 0:19:35
PilotGo-plugin-syscare数据库设计:热补丁状态跟踪与存储方案终极指南

PilotGo-plugin-syscare数据库设计:热补丁状态跟踪与存储方案终极指南

PilotGo-plugin-syscare数据库设计:热补丁状态跟踪与存储方案终极指南 【免费下载链接】PilotGo-plugin-syscare Introduce SysCare to PilotGo platform. 项目地址: https://gitcode.com/openeuler/PilotGo-plugin-syscare 前往项目官网免费下载&#xff1a…

2026/7/13 0:19:35
免费数字人平台怎么选?我把7类常见工具放进一张表,真正拉开差距的是水印、克隆和商用

免费数字人平台怎么选?我把7类常见工具放进一张表,真正拉开差距的是水印、克隆和商用

免费数字人平台怎么选?我把7类常见工具放进一张表,真正拉开差距的是水印、克隆和商用 很多人一找数字人工具,先看的都是三件事:有没有免费入口、首月多少钱、哪家看起来更划算。 但真正做过内容的人很快就会发现, 免费…

2026/7/13 0:19:35
AutoCAD 2024 3D壳体设计:从草图到STL打印文件的5步完整流程

AutoCAD 2024 3D壳体设计:从草图到STL打印文件的5步完整流程

AutoCAD 2024 3D壳体设计:从草图到STL打印文件的5步完整流程在工业设计和产品开发领域,3D壳体设计一直是工程师和设计师面临的核心挑战之一。无论是电子设备外壳、机械防护罩还是消费品包装,壳体不仅需要满足功能性需求,还要兼顾美…

2026/7/13 0:19:35
免费数字人平台怎么选?免费额度用完后,先看导出、克隆还是商用权限

免费数字人平台怎么选?免费额度用完后,先看导出、克隆还是商用权限

免费数字人平台怎么选?免费额度用完后,先看导出、克隆还是商用权限 很多人第一次找免费数字人平台,心里最先冒出来的判断通常很直接: 谁送的免费额度更多;谁首月价格更低;谁开会员看起来更便宜;…

2026/7/13 0:19:35
99.1.智能门禁-指纹+RFID+密码-基于STM32单片机物联网设计【硬件+APP+云平台】

99.1.智能门禁-指纹+RFID+密码-基于STM32单片机物联网设计【硬件+APP+云平台】

(1)硬件端 1. STM32F103C8T6:用于所有程序的中控和模块数据通信; 2. 0.96寸OLDE:用于显示当前设备状态; 3. 指纹模块(AS608):实现指纹录入以及开锁功能功能; …

2026/7/13 0:14:34

月新闻