P29 C++箭头运算符以及它对于结构体与类的指针关系

本期的主要内容是箭头运算符以及它对于结构体与类的指针可以做什么,最后实现我们自己的运算符重载。

01 为什么要使用运算符重载

从开发的角度而言,运算符重载的存在是为了提高开发效率,增加代码的可复用性,很多时候简化了代码

C++强大的原因之一是支持泛型编程。泛型编程使得算法可以独立于数据类型存在。自定义的数据类型通过操作符重载具有了和内建类型同样的使用接口,然后C++的模板加持下,你的算法可以利用这种接口一致性,实现泛化。

1.1 如何使用运算符重载

这是一个基本的 Entity 类,有一个输出提示语的 Print 函数。

#include <iostream>
#include <string>class Entity
{
public:void Print() const { std::cout << "Hello!" << std::endl; }
};int main()
{std::cin.get();
}

如果按照正常的使用方法,我们会这样创建对象。

int main()
{Entity e;e.Print();std::cin.get();
}

可如果是在堆上创建的,或者出于某种原因,程序中有一个指向它的指针,为了调用 Print 函数,该怎么办呢?这个时候就不能使用 . 了,下面的写法很明显是错的。

int main()
{Entity e;e.Print();Entity* ptr = &e;ptr.Print();std::cin.get();
}

因为 ptr 只是一个指针,也就是一个数值,不是对象,无法调用方法。

我们可以使用逆向引用 ptr 来实现调用 Print 函数(使用括号是因为符号的优先级的原因)。

int main()
{Entity e;e.Print();Entity* ptr = &e;(*ptr).Print();std::cin.get();

这样写当然没有问题,但它看起里有点笨重。

我们可以使用箭头运算符来简化这个操作。

int main()
{Entity e;e.Print();Entity* ptr = &e;ptr->Print();std::cin.get();
}

这样的操作就相当于逆向引用了 Entity 指针。

这就是它的全部内容了。

它只是一个快捷方式,成员变量也是同样的道理。

箭头运算符作为一个操作符,我们实际上可以重载它,并在你自定义类中使用它。

我们一起来看一个例子,来说明为什么要这么做以及怎么做。

假设我正在写一个智能指针的类,如下所示。

class ScopePtr
{
private:Entity* m_Obj;
public:ScopePtr(Entity* entity):m_Obj(entity){}~ScopePtr(){delete m_Obj;}
};

这是一个基本的 ScopePtr 类,当 Entity 超出范围时,这个类会自动删除它。

我可以这样使用它。

int main()
{ScopePtr entity = new Entity();std::cin.get();
}

我希望能够调用 Print 函数,该怎么做呢?

首先我不能用 . 符号,但我可以将 m_Obj 变成 public 的,或者写一个 GetObject 函数,返回一个 Entity 指针,类似下面这样写法。

int main()
{ScopePtr entity = new Entity();entity.GetObject()->Print();std::cin.get();
}

不过这方法看起来太乱了,我希望能够使用堆分配的 Entity 一样使用它,类似于下面这样用法。

int main()
{ScopePtr* entity = new Entity();entity->Print();std::cin.get();
}

这就是我们想要重载箭头运算符的原因。

重载箭头运算符。

总结

良好的重载除了提高写代码的效率,也往往降低了代码维护的成本,更容易减少bug,提高代码质量,增加可读性。

如果非要说带来了什么负面影响,我觉得往往还是人为的原因。没有做好抽象导致滥用运算符重载。如果设计不好接口的话,还是不要强行引入运算符重载,这样可能反而降低代码可读性,增加耦合。

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

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

相关文章

XIAO ESP32S3之模型部署

参考资料&#xff1a; sipeed AI教程&#xff1a;AI 指南 - Sipeed Wiki TinyMX:https://github.com/sipeed/TinyMaix EdgeLab:https://edgelab.readthedocs.io/zh-cn/latest/ sscma-example-esp32:GitHub - Seeed-Studio/sscma-example-esp32: Example of SenseCraft Mode…

【开源】基于Vue+SpringBoot的高校宿舍调配管理系统

项目编号&#xff1a; S 051 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S051&#xff0c;文末获取源码。} 项目编号&#xff1a;S051&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能需求2.1 学生端2.2 宿管2.3 老师端 三、系统…

Go语言与Java:一场编程语言之争

近年来&#xff0c;Go语言&#xff08;简称Go&#xff09;的崛起引发了对编程语言选择的深刻思考。Java&#xff0c;作为一门经典的编程语言&#xff0c;长期以来一直是企业级应用的首选。 然而&#xff0c;随着Go的逐渐成熟和广泛应用&#xff0c;人们开始重新评估Java是否仍…

Android系统源码中添加可编译运行执行程序,java

文章目录 Android系统源码中添加可编译运行执行程序&#xff0c;java1.Android设备中执行编译运行java代码2.编译执行jar包 Android系统源码中添加可编译运行执行程序&#xff0c;java 1.Android设备中执行编译运行java代码 新建一个文件夹&#xff0c;以及Java类的包路径 测…

linux 消息队列apache-activemq服务的安装

1.下载 官网下载地址&#xff1a;https://activemq.apache.org/ 操作如下&#xff1a; 2. 解压 执行&#xff1a;tar -zxvf apache-activemq-5.18.3-bin.tar.gz -C /user/ 3. 进入目录 执行&#xff1a;cd /user/apache-activemq-5.18.3 4.修改配置文件 执行&#xff1…

深度学习(二):pytorch基础知识

pytorch基础知识 张量&#xff08;Tensors&#xff09;自动微分&#xff08;Autograd&#xff09;模型构建数据加载和处理损失函数优化器&#xff08;Optimizers&#xff09;训练循环GPU加速模型保存和加载部署和推理PyTorch生态系统学习率调度&#xff08;Learning Rate Sched…

Java研学-IO流(二)

三 流资源类结构 1 Java中的流资源可操作文件中的数据 – IO流 ① 将数据写入到指定的文件中 ② 将数据从指定的文件中读出 2 分类 – 四大基流,八大子流 按照流向分:输入流和输出流 按照操作数据源的类型分: ① 字符流 Reader – 字符输入流 – InputStream – 基流 FileR…

基于单片机的电子密码锁设计

1&#xff0e;设计任务 利用AT89C51单片机为核心控制元件,设计一个简易的电子密码锁&#xff0c;可设置四位密码&#xff0c;输入错误三次&#xff0c;报警灯亮起&#xff08;红灯亮起&#xff09;&#xff0c;输入正确&#xff0c;绿灯闪烁三次。可通过LCD显示屏查看密码&…

LeetCode200. Number of Islands——DFS

文章目录 一、题目二、题解 一、题目 Given an m x n 2D binary grid grid which represents a map of 1’s (land) and 0’s (water), return the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertic…

智能生活:人工智能如何改变我们的日常

在科技迅猛发展的今天&#xff0c;人工智能&#xff08;AI&#xff09;已成为我们生活中的一部分。这项技术不仅仅是冷冰冰的代码和算法&#xff0c;而是一个全新的帮手&#xff0c;为我们的日常生活带来了前所未有的便利和智慧。本文旨在探讨人工智能如何影响我们的生活&#…

堆栈_栈实现队列

//请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作&#xff08;push、pop、peek、empty&#xff09;&#xff1a; // // 实现 MyQueue 类&#xff1a; // // // void push(int x) 将元素 x 推到队列的末尾 // int pop() 从队列的开头移除并返回元素…

Linux常用命令----history命令

文章目录 在Linux中&#xff0c;history命令是一个极其有用的工具&#xff0c;它可以帮助用户查看和管理之前执行过的命令历史。这个功能对于快速查找和重用之前的命令特别有帮助。下面&#xff0c;我们将通过一些实例&#xff0c;详细介绍history命令的使用方法。 1. 基本使用…

ElasticSearch03

高级客户端 参考&#xff1a;尚硅谷网课以及笔记 Java REST Client 有两种风格&#xff1a; Java Low Level REST Client &#xff1a;用于Elasticsearch的官方低级客户端。它允许通过HTTP与Elasticsearch集群通信。将请求编排和响应反编排留给用户自己处理。它兼容所有的Elas…

高效率:使用DBeaver连接spark-sql

提高运行效率一般采取底层使用spark引擎替换成hive引擎的方式提高效率&#xff0c;但替换引擎配置较为复杂考虑到兼容版本且容易出错&#xff0c;所以本篇将介绍使用DBeaver直接连接spark-sql快速操作hive数据库。 在spark目录下运行以下命令&#xff0c;创建一个SparkThirdSe…

11-28 SpringBoot1

约定大于配置 简化Spring开发, spring boot致力于简洁&#xff0c;让开发者写更少的配置&#xff0c;程序能够更快的运行和启动。它是下一代javaweb框架&#xff0c;并且它是spring cloud(微服务)的基础。dev-ops:开发者,运维者。 springboot特点:优点面试重点 1)为基于Spring…

C++学习专栏【基础知识1】C++程序结构命名空间关键字标识符三字符序列

一、C程序结构 让我们看一个简单的代码&#xff0c;它将打印Hello World一词。 #include <iostream> using namespace std; int main() {cout << "Hello World"; // prints Hello Worldreturn 0; } C语言定义了几个头文件&#xff0c;其中包含对你的程序…

系统部署安装-Centos7-Kafka

文章目录 安装离线安装下载安装 安装 离线安装 下载 可以前往kafka的官网进行下载 https://kafka.apache.org/downloads安装 1.创建安装目录 mdkir /opt/software/kafka mkdir /opt/kafka 2.解压 sudo tar -xzf kafka_2.12-3.6.0.tgz -C /opt/kafka --strip-components…

c语言编程题经典100例——(46~50例)

1、实现字符串转数字。 在C语言中&#xff0c;可以使用库函数atoi()将字符串转换为整数。该函数接受一个字符串作为参数&#xff0c;并返回对应的整数值。以下是一个示例代码&#xff1a; #include <stdio.h> #include <stdlib.h> int main() { char str[] …

操作符keyof的作用是什么?

keyof 是 TypeScript 中的一个操作符&#xff0c;用于获取一个类型&#xff08;通常是一个对象类型或接口&#xff09;的所有公共属性名组成的字符串字面量联合类型。它常常用于类型安全的属性访问和映射类型的定义。 什么时候使用 keyof&#xff1f; 类型安全的属性访问&…

Java | 数据一致性校验遇到的时间序列化格式不一致问题如何解决?

关注&#xff1a;CodingTechWork 需求 设计 在开发过程中&#xff0c;有数据一致性校验需求。如下设计&#xff1a; 对于一些安全数据进行加密处理&#xff0c;并将这个加密值进行存储。当再次查询时&#xff0c;对当前数据进行加密并比对之前的加密值&#xff0c;看是否一…