初识C++·类和对象(中)(3)

前言,最难的已经结束了,来点轻松了放松一下。

目录

1 流重载

2 const成员

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


1 流重载

C语言中printf和scanf是有局限性,只能直接打印内置类型,对于自定义类型就哦豁了,所以在C++中就引用了流的概念,也就是cou cin:

为什么说打印输出的时候不需要占位符,这就是因为流就是一个重载了的函数,所以每次打印的时候都会调用对应的重载函数,比如多次打印的时候,printf一下就打印出来了,但是对于流不行,它要调用许多次重载函数,才能打印出,这也就导致了C++效率不如C语言高,对于不同类型,都可以进行打印,那么我们显式实现一下流重载:

 首先我们要知道cout和cin来源于io流,作为一个全局对象出现的,所以cin的类型是istream,cout是ostream的,所以我们有一个参数的类型一定是ostream,传的参数是cout。

void Date::operator<<(ostream& out);//流重载

声明一下,我们先作为成员函数实现一下:

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

out是形参,用来接收cout,好了,我们实验一下:

	cout << d1;
	d1.operator<<(cout);

试问哪种形式是正确的?
不墨迹了,第二种是正确的,这与参数的使用顺序有关系,因为是成员函数,所以有一个默认的this指针,但是cout传给了第一个参数,也就是this,d1传给了ostream,这是不是倒反天罡了?
所以:

这样,就拿捏了?
并没有,因为有悖于常态,我们正常使用都是流在前,参数在后,这反过来了还,所以呢,自己控制参数就可以防止反过来的情况:

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

重载为全局函数就ok了,就可以使用cout << d1打印,但是又有问题了,如果我们连续打印呢?
这个其实和连续赋值是一样的,所以我们只需要加上返回值:

ostream& operator<<(ostream& out, const Date& d)//流重载
{
	out << d._year << "年" << d._month << "月" << d._day << "日" << endl;
	return out;
}

返回引用是因为原来的运算符重载返回的就是引用,所以我们也返回引用就行。

但是因为我们重载成了全局的,所以要访问就必须把成员变量置为公有的,怎么解决呢?
我们可以使用友元的方法,这里简单提一下,下篇文章介绍:
即我们把这个函数置为友元函数,也就是你是我的朋友,那我就可以用你的东西了:

class Date
{
    friend ostream& operator<<(ostream& out, const Date& d);
public:
private:
	int _year;
	int _month;
	int _day;
};

在函数名前面加一个friend,你是我的朋友,私有的成员变量你也可以访问了。

cin输入也是一样的,就不做演示了。


2 const成员

先来看这样一段代码:

int main()
{
	const Date d1(2020, 1, 17);
	d1.Print();
	return 0;
}

当d1被const修饰,我们还能调用成员函数吗?这是不可以的,因为const修饰了d1,也就说明d1的权限是const,但是成员函数指针是Date* const this,如果调用函数,就会存在权限放大的问题。

那么祖师爷的解决方法是,散装const来解决:

class Date
{
public:
	void Print()const;
private:
	int _year;
	int _month;
	int _day;
};
void Date::Print()const
{
	cout << _year << '-' << _month << '-' << _day << endl;
}

即是函数的后面加一个const,很奇怪对吧,补丁缝缝补补,这个const修饰的是Date* this的*this,加了const参数就变成了const Date* const this,就不存在权限放大的问题,因为const修饰*this的时候,指针指向的元素就不能被修改,所以对于+ -等函数,不修改成员变量的,都可以用const修饰。

那么如果成员函数用了const修饰,但是d1没有被const修饰,调用函数的时候会不会报错呢?

实际上是不会的,因为权限缩小是没有问题的。

所以写函数的时候,只要不是修改成员变量我们把const往上一加是没有问题的。


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

这是最后一个成员函数了,是比较简单的,我们看一段代码:

class A
{
public:
	A* operator&()
	{
		cout << "A* operator&" << endl;
		return this;
	}
	const A* operator&()const
	{
		cout << "const A* operator&" << endl;
		return this;
	}
private:
	int _a = 1;
	int _b = 2;
	int _c = 3;
};
int main()
{
	A a1;
	const A aa1;
	cout << &a1 << endl;
	cout << &aa1 << endl;
	return 0;
}

重载&符号其实就是取地址,也就是取自定义类型的地址,但是实际上如果我们不显示调用编译器默认的函数也够用,那么为什么还要单独拎出来呢?
比如返回地址的时候,我想整蛊一下别人呢,比如我返回空,返回假地址,当然平时不用显式定义,默认生成的就够用了。


类和对象中就结束了,终于结束了,挺多的,

感谢阅读!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

38. UE5 RPG 修改火球术的攻击方向以及按住Shift攻击

在前面&#xff0c;我们实现了火球术火球的制作&#xff0c;能够在释放火球术时&#xff0c;角色将播放释放技能动画&#xff0c;并实现了对火球的目标的服务器同步功能。 我们先回忆一下之前完成的内容。 在前面&#xff0c;我们先做了一个Actor&#xff0c;用于承载发射的火…

java线程-线程池

简介 工作原理 如何获取线程池对象 构造器的参数含义 注意事项 构造器-ThreadPoolExecutor // ArrayBlockingQueue 是一个有界的阻塞队列&#xff0c;它的内部实现是一个数组。有界的意思是它的容量是有限的&#xff0c;我们必须在创建 ArrayBlockingQueue 实例的时候指定容量…

01-服务与服务间的通信

这里是极简版&#xff0c;仅用作记录 概述 前端和后端可以使用axios等进行http请求 服务和服务之间也是可以进行http请求的spring封装的RestTemplate可以进行请求 用法 使用bean注解进行依赖注入 在需要的地方&#xff0c;自动注入RestTemplate进行服务和服务之间的通信 注…

[2021最新]大数据平台CDH存储组件kudu之启用HA高可用(添加多个master)

今天在做kudu高可用的时候没有参考官网&#xff0c;直接按照常规方式&#xff08;添加角色—>编辑属性—>启动&#xff09;结果发现报错&#xff1f;然后参考了一下文档之后发现这玩意儿还有点玄学&#xff0c;做一下记录。 1.添加两个master。kudu master有leader和foll…

深入解析Tomcat的工作流程

tomcat解析 Tomcat是一个广泛使用的开源Servlet容器&#xff0c;用于托管Java Web应用程序。理解Tomcat的工作流程对于开发人员和系统管理员来说是非常重要的。本文将深入探讨Tomcat的工作原理&#xff0c;包括请求处理、线程池管理、类加载、以及与Web服务器之间的通信。 ###…

思颜肌密:匠心独蕴,传世掠影

赋予延绵岁月以华彩乐章&#xff0c;将来自时间的承诺注入生活每分每秒&#xff0c;在思颜肌密的世界里&#xff0c;恒久之美并非遥不可及&#xff0c;它是艺术&#xff0c;亦是心意。华美节日翩然而至&#xff0c;思颜肌密拉开神秘帷幕&#xff0c;在惊鸿掠影中向世人展现传世…

[数据结构与算法]-什么是二叉树?

二叉树是一种数据结构&#xff0c;由节点组成&#xff0c;每个节点最多有两个子节点&#xff0c;分别称为左子节点和右子节点。二叉树的每个节点包含一个值&#xff0c;并且左子节点的值小于等于父节点的值&#xff0c;右子节点的值大于等于父节点的值。这个性质使得二叉树在搜…

Linux系统维护:增加空闲内存的大小,以便进程有足够的基础内存(空闲内存)来运行

目录 一、问题 二、解决思路 &#xff08;一&#xff09;问题分析 &#xff08;二&#xff09;思路 1. 清理缓存 2. 结束不必要的进程 3. 优化应用程序和服务 4. 增加物理内存 5、注意事项 三、实际处理 &#xff08;一&#xff09;结束不必要的程序 &#xff08;二…

批量规范化(batchnormalization)

ˆB 是小批量B的样本均值&#xff0c;σˆ B 是小批量B的样本标准差。应用标准化后&#xff0c;生成的小批量的平均 值为0和单位方差为1。由于单位方差&#xff08;与其他一些魔法数&#xff09;是一个主观的选择&#xff0c;因此我们通常包含 拉伸参数&#xff08;scale&#…

vulfocus靶场之redis命令执行cve-2022-0543漏洞复现

漏洞&#xff1a; Redis是著名的开源Key-Value数据库&#xff0c;其具备在沙箱中执行Lua脚本的能力。 Debian以及Ubuntu发行版的源在打包Redis时&#xff0c;不慎在Lua沙箱中遗留了一个对象package&#xff0c;攻击者可以利用这个对象提供的方法加载动态链接库liblua里的函数&…

初始化Git仓库时应该运行哪个命令?

文章目录 初始化Git仓库时&#xff0c;你应该运行git init这个命令。这个命令的作用是在你当前所在的目录里创建一个新的Git仓库。这样&#xff0c;你就可以在这个目录里开始使用Git来管理你的文件了。 下面我给你举个详细的例子来说明一下&#xff1a; 首先&#xff0c;你需要…

网络原理-IP协议

一、IP协议报头 版本号:用来表示IP协议的版本,现在常用的IP协议有两个版本,IPv4和IPv6&#xff0c;其他版本可能只存在于实验室中&#xff0c;并没有被广泛的使用。 首部长度:用来表示IP报头的长度,因为存在"选项"字段&#xff0c;所以IP报头是可变长的,此处单位为4…

春秋云镜 CVE-2023-51048

靶标介绍&#xff1a; S-CMS v5.0 被发现存在SQLI。 开启靶场 根据题目查找S-CMS v5.0漏洞&#xff0c;百度没有查询到&#xff0c;使用必应搜索S-CMS v5.0 查找到githubCVE-2023-51052的描述 S-CMS v5.0 was discovered to contain a SQL injection... CVE-2023-51052 Git…

Python程序设计 字典

教学案例十 字典 1. 判断出生地 sfz.txt文件中存储了地区编码和地区名称 身份证的前6位为地区编码&#xff0c;可以在sfz.txt文件中查询到地区编号对应的地区名称 编写程序&#xff0c;输入身份证号&#xff0c;查询并显示对应的地区名称 若该地区编码不在文件中&#xff0c;…

11.事件处理

事件处理 我们可以使用 v-on 指令 (简写为 ) 来监听 DOM 事件&#xff0c;并在事件触发时执行对应的 JavaScript。用法&#xff1a;v-on:click"methodName" 或 click"handler" 事件处理器的值可以是 内联事件处理器&#xff1a;事件被触发时执行的内联 J…

不同版本vue安装vue-router

vue-router 是vue官网发布的一个插件库&#xff0c;单页面路由。vue 和 vue-router 之间版本也需要对应。 vue2.x版本使用vue-router3.x版本&#xff0c;vue3.x使用vue-router4.x版本&#xff0c;根据自己的需要选择合适的版本 1、可以在安装前查看vue-router版本&#xff0c;…

微信小程序开发笔记

微信小程序开发笔记 1 微信小程序的项目结构 2 页面组成 一个微信小程序是由一个或多个页面组成的&#xff0c;这些页面被存放在pages目录中。下面以pages 目录下的index页面为例展示其组成部分&#xff0c;index页面的组成部分如下图所示。 由上图可知&#xff0c;index页面…

Swift-20-基础数据类型

数据定义 语法规则 先来看下下面的代码 import Cocoavar num1 "four" //a var num2: String "four" //b var num3 4 //c var num4: Int 4 //d上面的几行代码都能正常运行&#xff0c;其中a和b行等价&#xff0c;c和d行等价。区另就在于是否声…

SpringBoot集成Sleuth

引入Maven依赖 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-sleuth</artifactId></dependency> 配置yml文件 bootstrap.yml文件增加如下配置 注&#xff1a;这个配置不是必须要&#…

嵌入式Linux开发实操(十七):Linux Media Infrastructure userspace API

视频和无线电流媒体设备使用的Linux内核到用户空间API,包括摄像机、模拟和数字电视接收卡、AM/FM接收卡、软件定义无线电(SDR)、流捕获和输出设备、编解码器设备和遥控器。典型的媒体设备硬件如下: 媒体基础设施API就是用于控制此类设备的,分五个部分。 第一部分V4L2 API…