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.mzph.cn/bicheng/74677.shtml

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

相关文章

简历含金量的描述和注意事项!

背景 最近&#xff0c;在公司负责后端相关面试&#xff0c;简历看了不下 50 份&#xff0c;面试 10&#xff0c;纯手码 2000 多字&#xff0c;说说我对简历的看法&#xff0c;希望给大家一点启发。 教育经历 在众多求职面试中&#xff0c;我发现多数求职者容易忽视教育背景的…

cellnet框架概述

cellnet框架是一个‌高性能、组件化、多协议支持‌的开源服务器网络库&#xff0c;专注于游戏服务器、分布式的多进程通信等场景的开发。 一、核心特性 ‌支持多个主流协议&#xff0c;包括TCP、UDP、HTTP、WebSocket。并且抽象底层协议差异&#xff0c;统一网络连接管理‌。 …

【加密社】如何创建自己的币圈工具站

需要准备的工作 1.域名 2.服务器 周末的时候主要弄了快讯这方面的代码 我这里用的是星球日报的api&#xff0c;也可以订阅他们的rss&#xff0c;这部分在github上是开源的 https://github.com/ODAILY 我这里用的是WordPressonenav主题&#xff0c;然后用小工具在主页展示&am…

Docker学习笔记(十一)宿主机无法链接宿主机问题处理

故障排查优先级排序 服务状态 → 2. 端口监听 → 3. 防火墙 → 4. 权限配置 → 5. 网络路由 &#xff08;按此顺序可覆盖95%的常见问题‌15&#xff09; mysql镜像启动命令&#xff1a; docker run -p 3306:3306 --restartalways --name mysqlv8 -e MYSQL_ROOT_PASSWORDCd…

力扣:回溯算法

组合I class Solution {List<List<Integer>> result new ArrayList(); // 所有结果集List<Integer> list new ArrayList(); // 当前结果集public List<List<Integer>> combine(int n, int k) {dfs(n, k, 1);return result;}public void dfs(i…

华为HCIE鸿蒙应用开发认证靠谱吗?

在万物互联时代&#xff0c;智能终端设备的多样性与协同需求催生了操作系统的革新。华为HarmonyOS&#xff08;鸿蒙系统&#xff09;凭借其分布式架构与全场景能力&#xff0c;正成为打破设备边界、重塑用户体验的核心技术底座。HCIE鸿蒙应用开发认证作为华为认证体系的顶级资质…

23种设计模式-原型(Prototype)设计模式

原型设计模式 &#x1f6a9;什么是原型设计模式&#xff1f;&#x1f6a9;原型设计模式的特点&#x1f6a9;原型设计模式的结构&#x1f6a9;原型设计模式的优缺点&#x1f6a9;原型设计模式的Java实现&#x1f6a9;代码总结&#x1f6a9;总结 &#x1f6a9;什么是原型设计模式…

Oracle-rman restore遭遇RMAN-03002与ORA-19563

文章目录 在原DB上检查是否有重复的文件名&#xff1a;查看rman恢复的日志修正重名部分重新执行rman恢复结论&#xff1a; 在 RMAN 恢复过程中&#xff0c;遇到RMAN-03002连同ORA-19563:错误。 操作是将 Oracle 10.0.5的数据库备份从 RMAN備份恢复到另一台测试主机的同一个目录…

运维网络排查工具介绍与使用

作为一名运维工程师&#xff0c;日常工作中最令人头疼的莫过于各种网络故障。在过去一年半的运维生涯中&#xff0c;我积累了丰富的网络故障排查经验&#xff0c;今天就来和大家分享一下如何运用抓包工具&#xff08;Wireshark、tcpdump&#xff09;和网络排查工具&#xff08;…

解决vscode终端和本地终端python版本不一致的问题

&#x1f33f; 问题描述 本地终端&#xff1a; vscode终端&#xff1a; 别被这个给骗了&#xff0c;继续往下看&#xff1a; 难怪我导入一些包的时候老提示找不到&#xff0c;在本地终端就不会这样&#xff0c;于是我严重怀疑vscode中的python版本和终端不一样&#xff0c…

Sublime全局搜索快捷键Ctrl+Shift+F不能使用解决

问题描述&#xff1a; 在安装好Sublime后&#xff0c;我们使用快捷键进行全局搜索&#xff0c;发现没有反应&#xff0c;但是中文输入变成了繁体。 解决方案&#xff1a; 如截图&#xff0c;在关闭简繁切换的快捷键或者换成其他的就行

海康HTTP监听报警事件数据

http监听接收报警事件数据 海康获取设备报警事件数据两种方式&#xff1a; 1、sdk 布防监听报警事件数据,服务端布防。&#xff08;前面文章有示例&#xff09; 2、http监听接收报警事件数据&#xff0c;设备直接推送。 http监听接收报警事件数据&#xff0c;服务端可以使用n…

Python----计算机视觉处理(Opencv:图像边缘检测:非极大值抑制,双阈值筛选)

一、 高斯滤波 边缘检测本身属于锐化操作&#xff0c;对噪点比较敏感&#xff0c;所以需要进行平滑处理。这里使用的是一个5*5的高斯 核对图像进行消除噪声。 二、计算图像的梯度和方向 三、非极大值抑制 在得到每个边缘的方向之后&#xff0c;其实把它们连起来边缘检测就算完了…

Maven工具学习使用(四)——仓库

仓库分类 对于Mavne来说,仓库只分为两类:本地仓库和远程仓库。当Maven根据坐标查询寻找构件的时候,它首先会查看本地仓库,如果本地仓库存在此构件,则直接使用;如果本地仓库不存在此构件,或者需要查看是否有更新的构件版本,Maven就会去远程仓库查找,发现需要的构件之后…

Axure PR 9.0(发音:Ack-sure)原型图工具入门教程:链接交互

文章目录 引言Axure‌ RP 9I Axure RP9入门介绍元件库对两个元件进行连接页面:导航视图、概要母版交互II 链接交互从A页面跳转到B页面返回之前的页面see also引言 【 产品原型图】核心价值和实际应用场景:可视化需求,统一团队理解 https://blog.csdn.net/z929118967/articl…

docker远程debug

1. 修改 Java 启动命令 在 Docker 容器中启动 Java 程序时&#xff0c;需要添加 JVM 调试参数&#xff0c;jdk8以上版本 java -agentlib:jdwptransportdt_socket,servery,suspendn,address*:5005 -jar your-app.jar jdk8及以下版本&#xff1a; java -Xdebug -Xrunjdwp:tra…

K8S学习之基础五十四:jenkins新建测试流水线

jenkins新建测试流水线 新建任务 node(testak) {stage(第1步:从gitee上下载源代码) {git url: "https://gitee.com/akang007/jenkins-sample"script {build_tag sh(returnStdout: true, script: git rev-parse --short HEAD).trim()}}stage(第2步&#xff1a;基…

SylixOS 中 select 原理及使用分析

1、select接口简介 1.1 select接口使用用例 select 是操作系统多路 I/O 复用技术实现的方式之一。 select 函数允许程序监视多个文件描述符&#xff0c;等待所监视的一个或者多个文件描述符变为“准备好”的状态。所谓的”准备好“状态是指&#xff1a;文件描述符不再是阻塞状…

Spring WebFlux之ServerWebExchange

ServerWebExchange 是 Spring WebFlux 中的一个核心接口&#xff0c;用于表示服务器端处理的 HTTP 请求和响应。它封装了请求和响应的所有信息&#xff0c;并提供了相应的方法来操作这些信息。ServerWebExchange 在响应式编程模型中扮演着关键角色&#xff0c;支持非阻塞、异步…

Flutter 常见错误和坑

1. 状态管理问题 StatefulWidget 生命周期误用 // 错误&#xff1a;在 build 方法中修改状态 override Widget build(BuildContext context) {setState(() { counter; }); // 会导致无限重建循环return Text($counter); }// 正确&#xff1a;在事件处理中修改状态 Widget bui…