C++11QT复习 (五)

文章目录

    • **Day6-2 成员访问运算符重载(2025.03.25)**
    • **1. 复习**
    • **2. 成员访问运算符重载**
      • **2.1 箭头运算符 (`->`) 重载**
        • **(1) 语法**
      • **2.2 解引用运算符 (`*`) 重载**
        • **(1) 语法**
    • **3. 代码分析**
      • **3.1 代码结构**
      • **3.2 代码解析**
        • **(1) `Data` 类**
        • **(2) `SecondLayer` 类**
        • **(3) `ThirdLayer` 类**
      • **3.3 运行 `test()` 方法**
    • **4. 总结**

Day6-2 成员访问运算符重载(2025.03.25)

1. 复习

在上一节中,我们学习了 C++ 中的 输入输出流运算符重载(<<>> 以及 下标运算符 [] 和函数调用运算符 () 的重载。本节我们将重点学习 成员访问运算符(->*)的重载


2. 成员访问运算符重载

C++ 允许用户自定义类的成员访问方式,其中 ->(箭头运算符)和 *(解引用运算符)是最常见的运算符之一。它们通常用于模拟智能指针或多层指针访问。

2.1 箭头运算符 (->) 重载

(1) 语法
class A {
public:B* operator->();
};

作用

  • 允许 A 类的对象 像指针一样访问 B 类的成员
  • 典型用途是在 封装指针 的类(如智能指针)中重载 operator->,使得用户无需手动解引用即可访问目标对象的成员。

注意事项:

  1. 返回值必须是一个指针或者引用,否则无法继续访问成员变量或函数。
  2. 如果返回的是对象的引用,则可以实现多层 -> 重载。
  3. operator-> 不能改变调用对象自身,因此通常 不应该声明为 const 成员函数

2.2 解引用运算符 (*) 重载

(1) 语法
class A {
public:B& operator*();
};

作用

  • 允许 A 类的对象 像指针一样进行解引用
  • 常见于智能指针的实现,使 *ptr 直接返回对象的引用,方便访问其成员。

注意事项:

  1. 返回值一般是引用(如 B&),这样不会产生额外的拷贝。
  2. 适用于 封装指针 的类,如智能指针或代理类。

3. 代码分析

#include <iostream> 
using namespace std;class Data
{
public:Data(int data = 0):_data(data){cout << "Data(int data = 0)" << endl;}~Data(){cout << "~Data()" << endl; }int getData() const{return _data;}
private:int _data;
};class SecondLayer
{
public:SecondLayer(Data* pData):_pData(pData){cout << "SecondLayer(Data* pData)" << endl;}//重载 -> 运算符Data* operator->(){return _pData;}//解引用重载运算符Data& operator*(){return *_pData;}~SecondLayer(){cout << "~SecondLayer()" << endl;if (_pData){delete _pData;_pData = nullptr;}}private:Data* _pData;
};class ThirdLayer
{
public:ThirdLayer(SecondLayer* pSecond):_pSecond(pSecond){cout << "ThirdLayer(SecondLayer* pSecond)" << endl;}//重载 -> 运算符SecondLayer& operator->() {return *_pSecond;}~ThirdLayer(){cout << "~ThirdLayer()" << endl;if (_pSecond){delete _pSecond;_pSecond = nullptr;}}private:SecondLayer* _pSecond;
};void test()
{/*Data* data = new Data(1);SecondLayer* second = new SecondLayer(data);ThirdLayer* third = new ThirdLayer(second);*/SecondLayer second(new Data(10));//栈对象//A类的对象调用B类的成员函数/*cout << "&second : " << &second << endl;cout << "second.operator->() :" << second.operator->() << endl;*///  重载operator->  cout << "second.operator->()->getData() :" << second.operator->()->getData() << endl;cout << "second->getData() :" << second->getData() << endl;//  重载operator* cout << "(*second).getData()" << (*second).getData() << endl;ThirdLayer third(new SecondLayer(new Data(30)));//栈对象cout << "third->getData() : " << third->getData() << endl;//还原cout << "third.operator->().operator->()->getData()" << third.operator->().operator->()->getData();
}int main(int argc, char** argv)
{test();test();return 0;
}

3.1 代码结构

上面的代码实现了一个 三层封装 的指针代理类,分别是:

  • Data:数据类,包含一个 _data 成员变量。
  • SecondLayer:封装 Data* 指针,并重载 operator->operator*
  • ThirdLayer:封装 SecondLayer* 指针,并重载 operator->

3.2 代码解析

(1) Data
class Data
{
public:Data(int data = 0) : _data(data){cout << "Data(int data = 0)" << endl;}~Data(){cout << "~Data()" << endl;}int getData() const{return _data;}
private:int _data;
};
  • Data 类封装了一个 int 类型的数据 _data,提供了 getData() 方法用于获取数据值。
  • 构造函数、析构函数用于跟踪对象的创建和销毁。

(2) SecondLayer
class SecondLayer
{
public:SecondLayer(Data* pData) : _pData(pData){cout << "SecondLayer(Data* pData)" << endl;}// 重载 -> 运算符Data* operator->(){return _pData;}// 解引用运算符 *Data& operator*(){return *_pData;}~SecondLayer(){cout << "~SecondLayer()" << endl;if (_pData){delete _pData;_pData = nullptr;}}private:Data* _pData;
};
  • 封装 Data* 指针,并提供访问 Data 成员的方式
  • operator->() 返回 _pData 指针,使得 SecondLayer 对象 可以像指针一样使用 -> 访问 Data 的方法
  • operator*() 返回 _pData 所指向的 Data 对象的引用,使 *second 直接返回 Data 对象。

示例:

SecondLayer second(new Data(10));
cout << second->getData() << endl;  // 等价于 second.operator->()->getData()
cout << (*second).getData() << endl; // 等价于 second.operator*().getData()

(3) ThirdLayer
class ThirdLayer
{
public:ThirdLayer(SecondLayer* pSecond) : _pSecond(pSecond){cout << "ThirdLayer(SecondLayer* pSecond)" << endl;}// 重载 -> 运算符SecondLayer& operator->(){return *_pSecond;}~ThirdLayer(){cout << "~ThirdLayer()" << endl;if (_pSecond){delete _pSecond;_pSecond = nullptr;}}private:SecondLayer* _pSecond;
};
  • ThirdLayer 封装了 SecondLayer* 指针,并提供 operator->() 使其 可以像 SecondLayer 一样使用 -> 访问 Data 的方法
  • 实现两层 -> 重载,使得 ThirdLayer 可以连续访问 Data 成员。

示例:

ThirdLayer third(new SecondLayer(new Data(30)));
cout << third->getData() << endl;  // 等价于 third.operator->().operator->()->getData()

3.3 运行 test() 方法

void test()
{SecondLayer second(new Data(10));cout << "second->getData() :" << second->getData() << endl;cout << "(*second).getData()" << (*second).getData() << endl;ThirdLayer third(new SecondLayer(new Data(30)));cout << "third->getData() : " << third->getData() << endl;cout << "third.operator->().operator->()->getData() : " << third.operator->().operator->()->getData();
}

输出:

Data(int data = 0)
SecondLayer(Data* pData)
second->getData() : 10
(*second).getData() : 10
Data(int data = 0)
SecondLayer(Data* pData)
ThirdLayer(SecondLayer* pSecond)
third->getData() : 30
third.operator->().operator->()->getData() : 30
~ThirdLayer()
~SecondLayer()
~Data()
~SecondLayer()
~Data()
  • SecondLayer 允许访问 Data 对象。
  • ThirdLayer 允许访问 SecondLayer,最终可访问 Data
  • 多层指针访问的代理模式生效,并且析构时正确释放了内存。

4. 总结

运算符作用适用场景返回值类型
operator->()允许对象像指针一样访问成员智能指针、代理类指针或引用
operator*()允许对象像指针一样解引用智能指针、代理类引用

关键点:

  1. operator->() 需要返回指针或引用,可以连续调用 ->
  2. operator*() 需要返回对象的引用,避免拷贝,提高性能。
  3. 适用于封装指针的类,如智能指针和代理类

本节学习了 成员访问运算符 ->* 的重载,掌握它们的用法可以更好地理解 智能指针代理模式

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

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

相关文章

顺序表(C语言源码详解,附加测试代码)

目录 顺序表的基本实现 顺序表结构 顺序表的初始化 检查顺序表容量空间 顺序表的头插 顺序表的打印 顺序表的头删 顺序表的尾插 顺序表的尾删 顺序表的查找 ​编辑指定位置之前插入数据 指定位置删除数据 顺序表的销毁 顺序表的基本实现 顺序表结构 对顺序表的数…

draw.io费的思维导图软件、支持ProcessOn无水印导出。

draw.io的官方网址是 https://www.drawio.com/ 通过官方下载&#xff0c;本文只是安装及使用教程。 一、从别的思维导图软件导出并导入到Draw.io&#xff0c;&#xff08;ProcessOn为例&#xff09; 选择要付费下载流程图&#xff0c;并以ViSio格式导出&#xff08;后缀名…

springboot启动事件CommandLineRunner使用

什么是CommandRunner CommandRunner是springboot启动完成时会调用的一个runner 启动参数会传递到这个runner 我们能用来做一些初始化工作和缓存预热等工作 ApplicationRunner VS CommandRunner? 这两个Runner作用一样 只是得到的启动参数格式不一样 前者是一个Argument对象…

能源革命新突破:虚拟电厂赋能微电网智能调控,构建低碳生态新格局

在“双碳”目标的引领下&#xff0c;中央一号文件明确提出了“推进农村能源革命&#xff0c;深化绿色低碳技术应用”。作为能耗集中区域&#xff0c;产业园区如何实现清洁能源高效消纳与碳减排的目标成为了难题&#xff0c;中电国为推出的虚拟电厂与风光储充柴多能互补的微电网…

LabVIEW FPGA与Windows平台数据滤波处理对比

LabVIEW在FPGA和Windows平台均可实现数据滤波处理&#xff0c;但两者的底层架构、资源限制、实时性及应用场景差异显著。FPGA侧重硬件级并行处理&#xff0c;适用于高实时性场景&#xff1b;Windows依赖软件算法&#xff0c;适合复杂数据处理与可视化。本文结合具体案例&#x…

智慧高速,安全护航:视频监控平台助力高速公路高效运营

随着我国高速公路里程的不断增长&#xff0c;交通安全和运营效率面临着前所未有的挑战。传统的监控方式已难以满足现代化高速公路管理的需求&#xff0c;而监控视频平台的出现&#xff0c;则为高速公路的安全运营提供了强有力的技术支撑。高速公路视频监控联网解决方案 高速公路…

聚焦能源数字化转型,遨游通讯携智能化防爆手机亮相cippe2025

2025年3月26日&#xff0c;第二十五届中国国际石油石化技术装备展览会在北京中国国际展览中心&#xff08;新馆&#xff09;盛大开幕。作为全球石油石化行业的年度盛会&#xff0c;cippe2025北京石油展汇聚了来自全球75个国家和地区的近2000家企业&#xff0c;共同展示最新的石…

【银河麒麟系统常识】需求:安装.NET SDK

前提 网络状态正常(非离线安装)&#xff1b; 终端命令如下所示 根据不同系统的版本&#xff0c;自行选择&#xff0c;逐行执行即可&#xff1b; # 基于 Ubuntu/Debian 的银河麒麟系统 wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O…

K8S学习之基础五十:k8s中pod时区问题并通过kibana查看日志

k8s中pod默认时区不是中国的&#xff0c;挂载一个时区可以解决 vi pod.yaml apiVersion: v1 kind: Pod metadata:name: counter spec:containers:- name: countimage: 172.16.80.140/busybox/busybox:latestimagePullPolicy: IfNotPresentargs: [/bin/sh,-c,i0;while true;do …

创新前沿 | 接管主机即刻增量CDP备份,高效保障接管期间业务安全!

科力锐创新前沿系列 接管主机增量CDP备份 高效保障接管业务安全 当核心系统遭遇系统故障或误操作导致数据逻辑损毁等&#xff0c;往往需要将生产业务主机接管起来&#xff0c;继续对外提供服务&#xff0c;保障业务连续性。 然而&#xff0c;你的接管主机真的安全吗?一旦接…

Android平台毫秒级低延迟HTTP-FLV直播播放器技术探究与实现

一、前言 在移动互联网蓬勃发展的今天&#xff0c;视频播放功能已成为众多Android应用的核心特性之一。面对多样化的视频格式和传输协议&#xff0c;开发一款高效、稳定的视频播放器是许多开发者追求的目标。FLV&#xff08;Flash Video&#xff09;格式&#xff0c;尽管随着H…

STL之list

1. list的介绍和使用 1.1 list的介绍 list是可以在常数范围内在任意位置进行插入和删除的序列式容器&#xff0c;并且该容器可以前后双向迭代。list的底层是带头双向循环链表结构&#xff0c;双向链表中每个元素存储在互不相关的独立节点中&#xff0c;在节点中通过指针指向 其…

26考研——查找_树形查找_二叉排序树(BST)(7)

408答疑 文章目录 三、树形查找二叉排序树&#xff08;BST&#xff09;二叉排序树中结点值之间的关系二叉树形查找二叉排序树的查找过程示例 向二叉排序树中插入结点插入过程示例 构造二叉排序树的过程构造示例 二叉排序树中删除结点的操作情况一&#xff1a;被删除结点是叶结点…

C++异常处理完全指南:从原理到实战

文章目录 异常的基本概念基本异常抛出与捕获多类型异常捕获异常重新抛出异常安全异常规范&#xff08;noexcept&#xff09;栈展开与析构标准库异常总结 异常的基本概念 异常是程序运行时发生的非预期事件&#xff08;如除零、内存不足&#xff09;。C通过try、catch和throw提…

汽车方向盘开关功能测试的技术解析

随着汽车智能化与电动化的发展&#xff0c;方向盘开关的功能日益复杂化&#xff0c;从传统的灯光、雨刷控制到智能语音、自动驾驶辅助等功能的集成&#xff0c;对开关的可靠性、耐久性及安全性提出了更高要求。本文结合北京沃华慧通测控技术有限公司&#xff08;以下简称“慧通…

matplotlib——南丁格尔玫瑰

南丁格尔玫瑰图&#xff08;Nightingale Rose Chart&#xff09;&#xff0c;是一种特殊形式的柱状图&#xff0c;它以南丁格尔&#xff08;Florence Nightingale&#xff09;命名&#xff0c;她在1858年首次使用这种图表来展示战争期间士兵死亡原因的数据。 它将数据绘制在极坐…

【大模型基础_毛玉仁】4.4 低秩适配方法

目录 4.4 低秩适配方法4.4.1 LoRA1&#xff09;方法实现2&#xff09;参数效率 4.4.2 LoRA 变体1&#xff09;打破低秩瓶颈&#xff08;例ReLoRA&#xff09;2&#xff09;动态秩分配&#xff08;例AdaLoRA&#xff09;3&#xff09;训练过程优化&#xff08;例DoRA&#xff09…

融合YOLO11与行为树的人机协作智能框架:动态工效学优化与自适应安全决策

人工智能技术要真正发挥其价值&#xff0c;必须与生产生活深度融合&#xff0c;为产业发展和人类生活带来实际效益。近年来&#xff0c;基于深度学习的机器视觉技术在工业自动化领域取得了显著进展&#xff0c;其中YOLO&#xff08;You Only Look Once&#xff09;算法作为一种…

Java为什么要使用线程池?

前言1.对线程的管理更加的规范化2.降低创建线程和销毁线程的开销 前言 之前对于Java线程池的理解&#xff0c;一直停留在&#xff1a;对于Java中的多线程机制来说&#xff0c;如果不使用线程池的话&#xff0c;线程的使用就会变得杂乱无章。这一步。一直没有深入去理解为什么其…

告别分库分表,时序数据库 TDengine 解锁燃气监控新可能

达成效果&#xff1a; 从 MySQL 迁移至 TDengine 后&#xff0c;设备数据自动分片&#xff0c;运维更简单。 列式存储可减少 50% 的存储占用&#xff0c;单服务器即可支撑全量业务。 毫秒级漏气报警响应时间控制在 500ms 以内&#xff0c;提升应急管理效率。 新架构支持未来…