当前位置: 首页 > news >正文

C++类与对象基础(6)

       (注:本篇文章介绍部分内容时,需要用到上盘文章中日期类的代码,文章链接如下:C++类与对象基础(5)——日期类的实现-CSDN博客​​​​​​

目录

1. 运算符重载的相关补充:

1.1流运算符重载出现的问题:

1.2 针对上述问题的解决方法:

1.2.1 通过创建友元函数来实现对私有变量的访问:

2. const成员函数:

2.1 const成员函数基本介绍:

2.2 什么类型的函数需要加:

3.取地址及const取地址操作符重载:


4

1. 运算符重载的相关补充:

1.1流运算符重载出现的问题:

       在对对象进行打印时,一般会在类中编写一个用于打印的成员函数用于打印,即:

void Date::Print()
{cout << _year << " " << _month << " " << _day << endl;
}
int main()
{Date d(2024, 1, 8);d.Print();return 0;
}

运行结果如下:

在针对C++系列的第一篇文章中,就提到了在C++中,输出变量的方法不光只有printf函数,也可以使用流插入cout。上面所展示的代码虽然用到了cout,但是并不是直接调用,而是将cout封装在一个类的成员函数中,进行调用的。如果针对上面的对象d,直接利用cout进行打印,即:

int main()
{cout << d;return 0;
}

 运行代码,此时编译器会显示错误,即:

错误的原因在之前介绍运算符重载的时候提到过:对于自定义类型不能直接调用操作符,而是需要利用运算符重载。因此,为了实现自定义类型变量,即:d,在类中加入一个运算符重载,即:

(注:本篇文章所有的运算符重载都采用声明和定义分离的方式)

void Date::operator<<(ostream& out)
{out << _year << "年" << _month << "月" << _day << "日" << endl;
}

 运行下方代码:

int main()
{Date d1(2024, 1, 8);cout << d1;return 0;
}

此时仍然显示运行错误,但是将上方代码更改为下面的形式:

int main()
{Date d1(2024, 1, 8);/*cout << d1;*/d1 << cout;return 0;
}

代码成功运行,结果如下:

这是因为,对于双操作数的运算符,第一个参数是左操作数,第二个参数是右操作数,之前的文章中多次提到,对于成员函数来说,通常会有一个隐藏的参数,即this指针。所以,针对上面的运算符重载,其完整的参数应该为:

void Date::operator<<(Date* this, ostream& out)
{out << _year << "年" << _month << "月" << _day << "日" << endl;
}

所以,这就解释了为社么上面打印自定义类型d1时,cout<<d1这种形式会造成编译错误,而d1<<cout可以正常运行的原因。虽然将代码改为上述形式后,可以正常使用运算符cout,但是,与平时利用cout的使用习惯不符,改进的方法将在下一小节中进行介绍

1.2 针对上述问题的解决方法:

    上面提到,造成问题的原因时因为成员函数会有一个隐藏的参数this,为了避免此问题,可以将运算符重载的声明放在类之外,即作为一个全局函数,而非一个成员函数。对于全局函数,没有隐藏的参数this,因此可以人为定义参数的顺序,即:
 

void operator<<(ostream& out, const Date& d)
{out << d._year << "年" << d._month << "月" << d._day << "日" << endl;
}

虽然解决了操作数的顺序问题,但是由于在运算符中,三个成员变量  _year, _month, _day会受到访问限定符private的影响。因此,还需要解决成员变量的访问问题。对于此问题的解决,文章给出一种方法:


1.2.1 通过创建友元函数来实现对私有变量的访问

实现方法只需要在类中加上友元函数即可,即:
 

friend void operator<<(ostream& out, const Date& d);

(注:对于友元的相关知识将在下一篇文章中进行介绍,本文中只给出使用方法)

在加入了友元函数后,上述的运算符重载即可正常进行使用,即:

int main()
{Date d1(2024, 1, 8);cout << d1;return 0;
}

运行结果如下:

对于流提取,采用和流插入一样的实现方法,即:
创建运算符重载:

void operator>>(istream& in,Date& dd)
{in >> dd._year >> dd._month >> dd._day;
}

 在类中加入友元函数:

friend void operator>>(istream& in, Date& dd);

测试流提取的功能:
 

int main()
{Date d1(2024, 1, 8);cin >> d1;cout << d1;return 0;
}

运行结果如下:

2. const成员函数:

2.1 const成员函数基本介绍:

文章在介绍刘运算符重载的时候举了一个例子,即创建一个对象,并且将其打印,即:

Date d1(2024, 1, 8);

在之前对于引用进行介绍的文章中,提到了常饮用这个概念,即在引用的前面加上const,如果在上面给出的自定义类型d1前加上const,再对这个自定义类型进行打印,即:
 

int main()
{const Date d3(2024, 1, 9);d3.Print();return 0;
}

运行代码,此时编译器会显示错误。

具体错误原因与成员函数的隐藏变量this以及权限变化有关。在常饮用那一节就提到过:权限平移或者缩小而不能放大,对于前面加了const的自定义类型d3,当d3向函数Print传递参数时,其参数类型为const \, Date*,而函数Printthis的类型为Date* this,因此,在传递参数的过程中,涉及了权限放大。对于此问题的解决方法需要在函数后面加上一个const

(注:如果函数的声明和定义分离,则在声明和定义后都需要加上const

//函数声明
void Print() const;
//函数定义
void Date::Print() const
{cout << "void Date::Print() const" << endl;cout << _year << " " << _month << " " << _day << endl;
}

运行结果如下:

上面提到,权限不能放大,但是可以缩小或者平移,因此,非const类型的变量可以调用const类型的函数,例如:

int main()
{Date d4(2222, 2, 22);d4.Print();return 0;
}

运行结果如下:

 

2.2 什么类型的函数需要加const

在日期类中,给了很多的关于运算符重载的例子,例如:                               

bool operator>(Date& d);

利用上述运算符对下面两个自定义类型变量进行比较,即:

int main()
{const Date d3(2024, 1, 9);d3.Print();Date d4(2222, 2, 22);d4.Print();bool ret1 = (d3 > d4);cout << ret1 << endl;return 0;
}

运行代码,此时编译器会报错。

错误原因依旧涉及权限放大的问题,通过两个自定义类型的传递参数的顺序可以发现,d3在传递参数时,也涉及了权限的放大,因此,也需要将上述函数进行更改,即:

bool operator>(Date& d)const;
bool Date::operator>(Date& d) const
{if (_year > d._year){return true;}else if ((_year == d._year) && (_month > d._month)){return true;}else if ((_year == d._year) && (_month == d._month) && (_day > d._day)){return true;}else{return false;}
}

通过上面的两个例子可以看到,const类型的对象可以调用const类型函数,非const型的对象也可以调用const类型函数。因此,对于能够定义成const类型的成员函数,一般都需要加上const

前面的例子中,不难发现,在函数声明后面加上const的作用,主要是修饰*this,因此,如果一个成员函数涉及到对象的更改,则不能用const修饰。因此,对于日期类中的所有函数类型,可以加const的如下:

	bool operator==(Date& d)const;bool operator!=(Date& d)const;bool operator>(Date& d)const;bool operator>=(Date& d)const;bool operator<=(Date& d)const;bool operator<(Date& d)const;Date operator+(int day)const;Date operator-(int day)const;

需要注意,文章上面给出的流插入、流提取这两个函数由于不是成员函数,故不能用const修饰。

3.取地址及const取地址操作符重载:

       在前面的部分,介绍了默认成员函数中的4个,本部分将给出剩余的两个,由于这两个默认成员函数的实用意义远小于构造、析构、拷贝构造、赋值重载,因此文章只给出这两个函数的格式以及简单的应用:

      格式如下:

	//取地址操作符重载Date* operator&(){cout << "Date* operator&()" << endl;return this;}//const取地址操作符重载const Date* operator&() const{cout << "const Date* operator&() const" << endl;return this;}

       需要注意的时,这两个函数不光类型不同,其参数类型也不同,对于const取地址操作符重载,第一个const用于修饰函数的返回值,第二个const修饰的是*this。所以二者的参数类型不同。

下面给出测试代码来对取地址操作符重载以及const取地址操作符重载的调用进行演示:
 

const Date d3(2024, 1, 9);//d3.Print();Date d4(2222, 2, 22);//d4.Print();cout << &d3 << endl;cout << &d4 << endl;

运行结果如下:

        不难发现,自定义类型d3const修饰,因此优先调用const取地址操作符重载,自定义类型d4没有被const修饰,优先调用取地址操作符重载。 加入,在这两个函数中去掉一个,例如去掉取地址操作符重载,即:

//取地址操作符重载/*Date* operator&(){cout << "Date* operator&()" << endl;return this;}*///const取地址操作符重载const Date* operator&() const{cout << "const Date* operator&() const" << endl;return this;}

再运行下面的代码:

const Date d3(2024, 1, 9);//d3.Print();Date d4(2222, 2, 22);//d4.Print();cout << &d3 << endl;cout << &d4 << endl;

运行结果为:

当两个函数都去掉后,即:
 

	//取地址操作符重载/*Date* operator&(){cout << "Date* operator&()" << endl;return this;}*///const取地址操作符重载/*const Date* operator&() const{cout << "const Date* operator&() const" << endl;return this;}*/

再次运行下方代码:
 

cout << &d4 << endl;cout << &d3 << endl;

运行结果如下:

此时代码依旧正常运行。这是因为取地址操作符重载和const取地址操作符重载是默认构造函数,他的性质与构造函数类似,当不人为编写上述两个重载时,编译器会自动生成,当认为编写两个重载时,编译器会去调用已经编写好的。 

4. 勘误:

  由于个人能力有限,书中难免出现汉字拼写错误、代码意义解释错误、内容逻辑以及理解错误等不同类型的错误。首先感谢各位大佬能花掉自己宝贵的时间阅读此文章,愿大佬们斧正,发现错误可以通过私信联系,本人不胜感激。

相关文章:

C++类与对象基础(6)

(注&#xff1a;本篇文章介绍部分内容时&#xff0c;需要用到上盘文章中日期类的代码&#xff0c;文章链接如下&#xff1a;C类与对象基础(5)——日期类的实现-CSDN博客​​​​​​&#xff09; 目录 1. 运算符重载的相关补充&#xff1a; 1.1流运算符重载出现的问题&#x…...

OS_lab——分页机制与内存管理

认真阅读章节资料&#xff0c;掌握什么是分页机制 调试代码&#xff0c;掌握分页机制基本方法与思路 代码pmtest6.asm中&#xff0c;212行~237行&#xff0c;设置断点调试这几个循环&#xff0c;分析究竟在这里做了什么 掌握PDE&#xff0c;PTE的计算方法 动手画一画这个映…...

【面试】Redis基础知识

题目 为什么Redis是单线程却性能很高&#xff1f; Redis是一个高性能的基于内存的键值存储系统。它之所以能够达到高性能&#xff0c;主要有以下几个原因&#xff1a; 基于内存&#xff1a;Redis将数据存储在内存中&#xff0c;而不是硬盘上&#xff0c;这使得数据的读写速度…...

CentOS 9 (stream) 安装 Docker

1. Docker 简介 Docker 是一个开源的容器化平台&#xff0c;可帮助开发者轻松地创建、部署和运行应用程序。Docker 使开发人员能够在一个独立的容器中打包应用程序及其依赖项&#xff0c;这样他们就可以轻松地将应用程序移植到任何其他环境中。 Docker 主要由以下几个组件组成…...

vite中配置服务代理

前言 在vite中配置服务代理和webpack中大差不差,不过有些写法会有些不同 具体配置:配置 Vite {#configuring-vite} | Vite中文网 这里我写了一个demo,如下所示 开启node服务 我用express启动了一个服务,分别暴露两个接口 进行相关配置 在vite.config.ts文件中进行配置 e…...

kotlin 中 any, all , none

any 如果至少有一个元素匹配给定谓词&#xff0c;那么 any() 返回 true。 all 如果没有元素与给定谓词匹配&#xff0c;那么 none() 返回 true。 none 如果所有元素都匹配给定谓词&#xff0c;那么 all() 返回 true。 请注意&#xff0c;在一个空集合上使用任何有效的谓词去…...

如何使用 Python、Node.js 和 Go 创建基于 YOLOv8 的对象检测 Web 服务

1. 介绍 这是有关 YOLOv8 系列文章的第二篇。在上一篇文章中我们介绍了YOLOv8以及如何使用它&#xff0c;然后展示了如何使用 Python 和基于 PyTorch 的官方 YOLOv8 库创建一个 Web 服务来检测图像上的对象。 在本文中&#xff0c;将展示如何在不需要PyTorch和官方API的情况下…...

pod节点jar包替换流程

1、查找到该docker容器 docker ps | grep backend # ./entrypoint.sh文件启动的那个容器2、替换jar 包 mv xxx.jar app.jar docker cp app.jar 66bc6fea9fb5:/home/aimind/3、重启容器 docker restart 66bc6fea9fb5 4、重启容器后进行功能验证 功能验证没问题了&#xff0c;再…...

Pytorch:torch.nn.Module

torch.nn.Module 是 PyTorch 中神经网络模型的基类&#xff0c;它提供了模型定义、参数管理和其他相关功能。 以下是关于 torch.nn.Module 的详细说明&#xff1a; 1. torch.nn.Module 的定义&#xff1a; torch.nn.Module 是 PyTorch 中所有神经网络模型的基类&#xff0c;…...

传统图像处理学习笔记更新中

文章目录 传统图像处理颜色空间高斯滤波腐蚀和膨胀开运算和闭运算如何求一张图片的均值?线性插值双线性插值仿射变换透视变换常见的边缘检测算子Sobel 算法Canny 算法Hough 变换原理(直线和圆检测)找轮廓(findCountours)单应性(homography)原理...

Hyperledger Fabric Java App Demo

编写一个应用程序来连接到 fabrc 网络中&#xff0c;通过调用智能合约来访问账本. fabric gateway fabric gateway 有两个项目&#xff0c;一个是 fabric-gateway-java , 一个是 fabric-gateway。 fabric-gateway-java 是比较早的项目&#xff0c;使用起来较为麻烦需要提供一…...

Doris 在工商信息商业查询平台的湖仓一体建设实践(02)

信息服务行业可以提供多样化、便捷、高效、安全的信息化服务,为个人及商业决策提供了重要支撑与参考。本文以某工商信息商业查询平台为例,介绍其从传统 Lambda 架构到基于 Doris Multi-Catalog 的湖仓一体架构演进历程。同时通过一系列实践,展示了如何保证数据的准确性和实时…...

218.【2023年华为OD机试真题(C卷)】攀登者2(动态规划-JavaPythonC++JS实现)

🚀点击这里可直接跳转到本专栏,可查阅顶置最新的华为OD机试宝典~ 本专栏所有题目均包含优质解题思路,高质量解题代码(Java&Python&C++&JS分别实现),详细代码讲解,助你深入学习,深度掌握! 文章目录 一. 题目-攀登者2二.解题思路三.题解代码Python题解代码…...

【精通C语言】:分支结构switch语句的灵活运用

&#x1f3a5; 屿小夏 &#xff1a; 个人主页 &#x1f525;个人专栏 &#xff1a; C语言详解 &#x1f304; 莫道桑榆晚&#xff0c;为霞尚满天&#xff01; 文章目录 &#x1f4d1;前言一、switch语句1.1 语法1.2 代码示例 二、switch的控制语句2.1 break2.2 defualt子句 三、…...

数据结构和算法-数据结构的基本概念和三要素和数据类型和抽象数据类型

文章目录 总览数据结构的基本概念总览数据早期和现代的计算机处理的数据数据元素-描述一个个体数据对象-一类数据元素什么是数据结构小结 数据结构的三要素总览逻辑结构-集合结构逻辑结构-线性结构逻辑结构-树形结构逻辑结构-图形结构逻辑结构-小结数据的运算物理结构&#xff…...

LeetCode 2353. 设计食物评分系统【设计,哈希表,有序集合;堆+懒删除】1781

本文属于「征服LeetCode」系列文章之一&#xff0c;这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁&#xff0c;本系列将至少持续到刷完所有无锁题之日为止&#xff1b;由于LeetCode还在不断地创建新题&#xff0c;本系列的终止日期可能是永远。在这一系列刷题文章…...

Redis (三)

1、redis复制 简单的概括就是主从复制&#xff0c;master以写为主&#xff0c;Slave以读为主&#xff0c;当master数据发生变化的时候&#xff0c;自动将更新的数据异步同步到其他的slave是数据库。 使用这种机制的话&#xff0c;可以做到读写分离&#xff0c;可以减轻主机负担…...

CompletableFuture超详解与实践

0.背景 一个接口可能需要调用 N 个其他服务的接口&#xff0c;这在项目开发中还是挺常见的。举个例子&#xff1a;用户请求获取订单信息&#xff0c;可能需要调用用户信息、商品详情、物流信息、商品推荐等接口&#xff0c;最后再汇总数据统一返回。 如果是串行&#xff08;按…...

Maven之私服

1 介绍 团队开发现状分析私服是一台独立的服务器&#xff0c;用于解决团队内部的资源共享与资源同步问题Nexus Sonatype公司的一款maven私服产品 下载地址&#xff1a;https://help.sonatype.com/repomanager3/download win版安装包&#xff1a;https://pan.baidu.com/s/1wk…...

#define宏定义的初探

前言&#xff1a; 最基本的#define定义方式 #define可以定义宏&#xff0c;这点相信大家并不陌生&#xff0c;其定义的方式十分简单&#xff0c;给大家随便来一个最简单、最基础的定义方式看看&#xff1a; #include<stdio.h> #define a 3 int main() { printf(&quo…...

机器学习 -决策树的案例

场景 我们对决策树的基本概念和算法其实已经有过了解&#xff0c;那我们如何利用决策树解决问题呢&#xff1f; 构建决策树 数据准备 我们准备了一些数据如下&#xff1a; # 定义新的数据集 new_dataSet [[晴朗, 是, 高, 是],[雨天, 否, 低, 否],[阴天, 是, 中, 是],[晴朗…...

04、Kafka ------ 各个功能的作用解释(Cluster、集群、Broker、位移主题、复制因子、领导者副本、主题)

目录 启动命令&#xff1a;CMAK的用法★ 在CMAK中添加 Cluster★ 在CMAK中查看指定集群★ 在CMAK中查看 Broker★ 位移主题★ 复制因子★ 领导者副本和追随者副本★ 查看主题 启动命令&#xff1a; 1、启动 zookeeper 服务器端 小黑窗输入命令&#xff1a; zkServer 2、启动 …...

1、C语言:数据类型/运算符与表达式

数据类型/运算符/表达式 1.数据类型与长度2.常量3.声明4. 运算符5. 表达式 1.数据类型与长度 基本数据类型 类型说明char字符型&#xff0c;占用一个字节&#xff0c;可以存放本地字符集中的一个字符int整型&#xff0c;通常反映了所有机器中整数的最自然长度float单精度浮点…...

[ffmpeg系列 03] 文件、流地址(视频)解码为YUV

一 代码 ffmpeg版本5.1.2&#xff0c;dll是&#xff1a;ffmpeg-5.1.2-full_build-shared。x64的。 文件、流地址对使用者来说是一样。 流地址(RTMP、HTTP-FLV、RTSP等)&#xff1a;信令完成后&#xff0c;才进行音视频传输。信令包括音视频格式、参数等协商。 接流的在实际…...

python算法每日一练:连续子数组的最大和

这是一道关于动态规划的算法题&#xff1a; 题目描述&#xff1a; 给定一个整数数组 nums&#xff0c;请找出该数组中连续子数组的最大和&#xff0c;并返回这个最大和。 示例&#xff1a; 输入&#xff1a;[-2, 1, -3, 4, -1, 2, 1, -5, 4] 输出&#xff1a;6 解释&#xff…...

一个vue3的tree组件

https://download.csdn.net/download/weixin_41012767/88709466...

新手练习项目 4:简易2048游戏的实现(C++)

名人说&#xff1a;莫听穿林打叶声&#xff0c;何妨吟啸且徐行。—— 苏轼《定风波莫听穿林打叶声》 Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#xff09; 目录 一、效果图二、代码&#xff08;带注释&#xff09;三、说明 一、效果图 二、代码&#xff08;带…...

2023年度总结:技术沉淀、持续学习

2023年度总结&#xff1a;技术沉淀、持续学习 一、引言 今年是我毕业的第二个年头&#xff0c;也是完整的一年&#xff0c;到了做年终总结的时候了 这一年谈了女朋友&#xff0c;学习了不少技术&#xff0c;是充实且美好的一年&#xff01; 首先先看年初定的小目标&#xf…...

Unity 利用UGUI之Slider制作进度条

在Unity中使用Slider和Text组件可以制作简单的进度条。 首先在场景中右键->UI->Slider&#xff0c;新建一个Slider组件&#xff1a; 同样方法新建一个Text组件&#xff0c;最终如图&#xff1a; 创建一个进度模拟脚本&#xff0c;Slider_Progressbar.cs using System.C…...

OCS2 入门教程(四)- 机器人示例

系列文章目录 前言 OCS2 包含多个机器人示例。我们在此简要讨论每个示例的主要特点。 System State Dim. Input Dim. Constrained Caching Double Integrator 2 1 No No Cartpole 4 1 Yes No Ballbot 10 3 No No Quadrotor 12 4 No No Mobile Manipul…...

优惠券网站是不是很难做/谷歌sem服务商

在学习过程中主要感觉在学习方法的选择上也要下功夫思考&#xff0c;找到一个比较合适的学习方法&#xff0c;以下是个人感觉有用的方法&#xff1a; 1) 看视频。 看视频时要认真看、记、体会每一个动作&#xff0c;拿视频中教练讲的跟自己实际的动作作对比&#xff0c;以找到…...

深圳 网站开发公司电话/网站的排名优化怎么做

概念meta-data就像其名一样&#xff0c;主要用来定义一些组件相关的配置值。按照官方定义&#xff0c;metadata是一组供父组件使用的名值对(name-value pair)&#xff0c;因此相应的meta-data元素应该定义在相应的组件中。即如果想在activity中使用metadata&#xff0c;那么met…...

做网站外包公司/优化落实疫情防控

1.题目描述&#xff1a; 2.算法分析&#xff1a; 首先&#xff0c;要过滤掉多余的空格&#xff0c;我们如果一个一个删除空格是一件很麻烦的事&#xff0c;不妨我们可以从每个单词的后面加一个空格&#xff0c;这样是不是会比把多余空格删除好一些呢。怎么做&#xff1f; 一个…...

电影购票网站开发背景/怎样做好网络营销推广

import pandas as pddata pd.DataFrame() series pd.Series({"x":1,"y":2},name"a") data data.append(series) print(data) data data.append(series) print(data)x y a 1.0 2.0x y a 1.0 2.0 a 1.0 2.0...

网站制作一条龙全包/每日英语新闻

1、配置git 2、create git repository 3、git-->add commit Directory 4、提交代码 git remote add origin https://github.com/lujianing/ueditor.git git push -u origin master 注意&#xff1a;如果报错-->先fetch再merge-->push...

如何让自己的网站被搜索引擎收录/在线crm网站建站

nohup command > /dev/null 2>&1 &...