【C++】:类和对象(中):const成员 || 取地址及const取地址操作符重载

在这里插入图片描述

📪1.const成员

📪将const修饰的“成员函数”称之为const成员函数,const修饰类成员函数,实际修饰该成员函数隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改
在这里插入图片描述
🎈首先我们来想一想为什么在C++中我们的输出流能自动识别类型呢?
🎈这里给大家分享一个文档以及我给大家查到的知识
在这里插入图片描述
🎈点击查看官方C++库
在这里插入图片描述
🎈C++委员会已经帮我们写好的C++库 我们只需要写很短小的一截就可以自动识别类型 这是因为函数重载 类型匹配 函数名修饰规则的原因
所以我们标准的cout重载应该按照以下的语法规则书写

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

📟输入的语法规则则为

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

📮见下图能否帮助你理解一下
在这里插入图片描述
在这里插入图片描述
🎓下面给大家总结一下
🎓运算符重载
C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似
函数名字为:关键字operator后面接需要重载的运算符符号
函数原型:返回值类型 operator操作符(参数列表)
🎓注意:
不能通过连接其他符号来创建新的操作符:比如operator
重载操作符必须有一个类类型参数
用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不能改变其含义
作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏的this
.* :: sizeof ?: . 注意以上5个运算符不能重载。这个经常在笔试选择题中出现
🎓*注意:.不会涉及 在后面的笔试题中可能会出现 在实际的工作中基本不会遇见

🔫2.取地址及const取地址操作运算符重载

🎾下面我们正式进入今天的主题
来看下面两段代码

//	const对象和非const对象都可以调用const成员函数
//	const Date d1(2023, 10, 31);
//	d1.Print();
//
//	Date d2(2023, 1, 1);
//	d2.Print();

在这里插入图片描述
📢首先要记住一点的就是我们在前面已经讲过了就是权限可以平移和缩小但是不能放大
🔫d1里面传的本质是d1的地址也就是const Date*
而函数调用的参数里面却又是Date* this 所以这里是权限的放大 我们需要添加一个const 那么问题又来了 const加到哪里合适呢?看上面图片和代码
📲只要是不修改成员的日期类对象都可以加上const 这样让我们的const和非const成员都可以传过来 看下面代码

#include "Date.h"Date::Date(int year, int month, int day)
{_year = year;_month = month;_day = day;if (_year < 1 ||_month < 1 || _month > 12 ||_day < 1 || _day > GetMonthDay(_year, _month)){//assert(false);Print();cout << "日期非法" << endl;}
}void Date::Print() const
{cout << _year << "/" << _month << "/" << _day << endl;
}bool Date::operator==(const Date& y)  const
{return _year == y._year&& _month == y._month&& _day == y._day;
}// d1 != d2
bool Date::operator!=(const Date& y) const
{return !(*this == y);
}bool Date::operator>(const Date& y) const
{if (_year > y._year){return true;}else if (_year == y._year && _month > y._month){return true;}else if (_year == y._year && _month == y._month && _day > y._day){return true;}return false;
}bool Date::operator>=(const Date& y) const
{return *this > y || *this == y;
}bool Date::operator<(const Date& y) const
{return !(*this >= y);
}bool Date::operator<=(const Date& y)  const
{return !(*this > y);
}int Date::GetMonthDay(int year, int month)
{assert(year >= 1 && month >= 1 && month <= 12);int monthArray[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30,31 };if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))return 29;return monthArray[month];
}// d1 += 100
Date& Date::operator+=(int day)
{if (day < 0){return *this -= (-day);}_day += day;while (_day > GetMonthDay(_year, _month)){_day -= GetMonthDay(_year, _month);++_month;if (_month == 13){_year++;_month = 1;}}return *this;
}Date Date::operator+(int day) const
{Date tmp(*this);tmp += day;return tmp;
}
// 
// d1 += 100
//Date& Date::operator+=(int day)
//{
//	//Date d = *this + day;
//	//*this = d;
//
//	*this = *this + day;
//	return *this;
//}
//
//Date Date::operator+(int day)
//{
//	Date tmp(*this);
//
//	tmp._day += day;
//	while (tmp._day > GetMonthDay(tmp._year, tmp._month))
//	{
//		tmp._day -= GetMonthDay(tmp._year, tmp._month);
//
//		++tmp._month;
//
//		if (tmp._month == 13)
//		{
//			tmp._year++;
//			tmp._month = 1;
//		}
//	}
//
//	return tmp;
//}Date& Date::operator-=(int day)
{if (day < 0){return *this += (-day);}_day -= day;while (_day <= 0){--_month;if (_month == 0){--_year;_month = 12;}_day += GetMonthDay(_year, _month);}return *this;
}Date Date::operator-(int day) const
{Date tmp(*this);tmp -= day;return tmp;
}// ++d1
Date& Date::operator++()
{*this += 1;return *this;
}// d1++
Date Date::operator++(int)
{Date tmp(*this);*this += 1;return tmp;
}Date& Date::operator--()
{*this -= 1;return *this;
}Date Date::operator--(int)
{Date tmp(*this);*this -= 1;return tmp;
}// d1 - d2
int Date::operator-(const Date& d) const
{// 假设左大右小int flag = 1;Date max = *this;Date min = d;// 假设错了,左小右大if (*this < d){max = d;min = *this;flag = -1;}int n = 0;while (min != max){++min;++n;}return n * flag;
}//void Date::operator<<(ostream& out)
//{
//	out << _year << "年" << _month << "月" << _day << "日" << endl;
//}ostream& operator<<(ostream& out, const Date& d)
{out << d._year << "年" << d._month << "月" << d._day << "日" << endl;return out;
}istream& operator>>(istream& in, Date& d)
{in >> d._year >> d._month >> d._day;return in;
}

🚿思考下面问题
📲1. const对象可以调用非const成员函数吗?
📲2. 非const对象可以调用const成员函数吗?
📲解析:能定义成const的成员函数都应该定义成为const 这样对const对象和非const成员来说都可以调用 要修改成员变量的成员函数不能定义成const
📲上述问题归根结底还是我们的权限的放大缩小和平移的问题

//class A
//{
//public:
//    A(int a)
//        :_a(a)
//    {
//        cout << "A(int a = 0)" << endl;
//    }
//private:
//    int _a;
//};
//
//namespace bit
//{
//    class Date
//    {
//    public:
//        //Date(int year, int month, int day)
//        //{
//        //    // 函数体内初始化
//        //    _year = year;
//        //    _month = month;
//        //    _day = day;
//
//        //    //_ref = year;
//        //    //_n = 1;
//        //}
//
//        //Date(int year, int month, int day)
//        //    :_year(year)
//        //    ,_month(month)
//        //    ,_day(day)
//        //    ,_ref(year)
//        //    ,_n(1)
//        //{
//        //    // 初始化列表
//        //    // 
//        //}
//
//        Date(int year, int month, int day)
//           :_year(2)
//           ,_ref(year)
//           ,_n(1)
//           ,_aa(10)
//        {
//            // 剩下3个成员没有在初始化列表显示写出来定义
//            // 但是他也会定义,只是内置类型默认给的随机值
//            // 如果是自定义类型成员会去调用它的默认构造函数
//            
//            // 函数体内初始化
//            _year = year;
//            _month = month;
//            _day = day;
//        }
//
//    private:
//        // 声明
//        int _year = 1; // 缺省值
//        int _month = 1;
//        int _day;
//
//        A _aa;        // 定义类型成员(且该类没有默认构造函数时)
//
//        int& _ref;	  // 引用 : 必须在定义的时候初始化
//        const int _n; // const : 必须在定义的时候初始化
//    };
//}// 初始化列表解决的问题:
// 1、必须在定义的地方显示初始化  引用  const   没有默认构造自定义成员
// 2、有些自定义成员想要显示初始化,自己控制
// 尽量使用初始化列表初始化
// 构造函数能不能只要初始化列表,不要函数体初始化
// 不能,因为有些初始化或者检查的工作,初始化列表也不能全部搞定
// 80-100%初始化列表搞定,还有需要用函数体,他们可以混着用
class Stack
{
public:Stack(int n = 2):_a((int*)malloc(sizeof(int)*n)),_top(0),_capacity(n){//...//cout << "Stack(int n = 2)" << endl;if (_a == nullptr){perror("malloc fail");exit(-1);}memset(_a, 0, sizeof(int) * n);}//...int* _a;int _top;int _capacity;
};

📲上述代码给大家写了一下初始化列表和函数体的运用规则 对于const成员和引用成员必须在初始化列表初始化 不能再函数体内部初始化 初始化列表也可以运用函数 比如malloc 然后在函数体内判断是否为NULL 在进行memset操作
📲来看下面的一道面试题

class A
{
public:A(int a):_a1(a), _a2(_a1){}void Print() {cout << _a1 << " " << _a2 << endl;}
private:int _a2;int _a1;
};int main() 
{A aa(1);aa.Print();
}

在这里插入图片描述
🎒根据声明的先后顺序 因此我们这里的_a1=1 _a2是随机值
🎒下篇给大家讲解类和对象下篇 到那是我们就正式结束了我们的类和对象 我们就要正式进入内存管理和模板以及STL的学习了

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

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

相关文章

layui form表单 调整 label 宽度

这个可以调整所有label .layui-form-label {width: 120px !important; } .layui-input-block {margin-left: 150px !important; }情况是这样的&#xff0c;表单里有多个输入框&#xff0c;只有个别label 是长的&#xff0c;我就想调整一下个别长的&#xff0c;其它不变 <di…

非关系型数据库Redis的安装【Linux】及常用命令

前言 Redis&#xff08;Remote Dictionary Server&#xff09;是一种开源的内存数据库管理系统&#xff0c;它以键值存储方式来存储数据&#xff0c;并且支持多种数据结构&#xff0c;如字符串、哈希、列表、集合、有序集合等。Redis最初由Salvatore Sanfilippo开发&#xff0c…

华为升腾C92安装windows NAS

华为升腾C92安装windows NAS NAS&#xff08;Network Attached Storage&#xff1a;网络附属存储&#xff09;&#xff0c;我们之前所了解的群晖&#xff0c;也仅仅是NAS当中的一个品牌运营而已。 这次&#xff0c;我决定在C92上面试着安装Windows NAS。虽然群晖NAS是基于Linu…

sitespeedio.io 前端页面监控安装部署接入influxdb 到grafana

1.docker部署influxdb,部署1.8一下&#xff0c;不然语法有变化后面用不了grafana模板 docker run -d -p 8086:8086 --name influxdb -v $PWD/influxdb-data:/var/lib/influxdb influxdb:1.7.11-alpine docker exec -it influxdb_id bash #influx create user admin with pass…

【计算机网络】运输层

概述运输层服务 运输层协议为运行在不同主机上的应用程序提供了逻辑通信功能。 运输层协议是在端系统中而不是在路由器中实现的。 运输层和网络层的关系&#xff1a; 网络层提供主机之间的逻辑通信&#xff0c;而运输层为**运行在不同主机上的应用程序&#xff08;进程&#…

「视频编码软件」Media Encoder(Me) 2024 Mac/win中文版下载安装

Adobe Media Encoder(Me) 2024是一款专业的视频编码工具&#xff0c;它可以将各种视频格式进行转换、压缩和编码&#xff0c;以满足不同媒体平台和设备的需求。 以下是 Media Encoder 2023 的主要功能和新增功能&#xff1a; 视频编码和转换&#xff1a;支持将各种视频格式进…

Pytorch网络模型训练

现有网络模型的使用与修改 vgg16_false torchvision.models.vgg16(pretrainedFalse) # 加载一个未预训练的模型 vgg16_true torchvision.models.vgg16(pretrainedTrue) # 把数据分为了1000个类别print(vgg16_true) 以下是vgg16预训练模型的输出 VGG((features): S…

2023全新小程序广告流量主奖励发放系统源码 流量变现系统 带安装教程

2023全新小程序广告流量主奖励发放系统源码 流量变现系统 分享软件&#xff0c;吃瓜视频&#xff0c;或其他资源内容&#xff0c;通过用户付费买会员来变现&#xff0c;用户需要付费&#xff0c;有些人喜欢白嫖&#xff0c;所以会流失一部分用户&#xff0c;所以就写了这个系统…

CSGO饰品价格暴跌的原因分析

CSGO饰品暴跌3个月&#xff0c;盘点6大原因 今天我们来聊一下CSGO饰品市场的情况。大部分装备从3月份开始就一直持续走低&#xff0c;到现在已经是7月份了&#xff0c;还有部分饰品呈阴跌趋势。整个市场沉寂一片&#xff0c;还有些悲观主义者天天在吆喝&#xff1a;市场崩盘了&…

【论文阅读笔记】GLM-130B: AN OPEN BILINGUAL PRE-TRAINEDMODEL

Glm-130b:开放式双语预训练模型 摘要 我们介绍了GLM-130B&#xff0c;一个具有1300亿个参数的双语(英语和汉语)预训练语言模型。这是一个至少与GPT-3(达芬奇)一样好的100b规模模型的开源尝试&#xff0c;并揭示了如何成功地对这种规模的模型进行预训练。在这一过程中&#xff0…

香港金融科技周2023:AIGC重塑金融形态

10月31日&#xff0c;由香港财经事务及库务局与投资推广署主办的“香港金融科技周2023大湾区专场”盛大启幕。中国AI决策领先企业萨摩耶云科技集团创始人、董事长兼 CEO林建明受邀参加圆桌会议&#xff0c;与中国内地、香港以及全球金融科技行业顶尖人才、创新企业、监管机构和…

【C++】特殊类设计

文章目录 一、设计一个类&#xff0c;不能被拷贝二、设计一个类&#xff0c;不能被继承三、设计一个类&#xff0c;只能在栈上创建对象四、设计一个类&#xff0c;只能在堆上创建对象五、设计一个类&#xff0c;只能创建一个对象(单例模式) 在某些特殊的场景下&#xff0c;我们…

“免单优选模式:引爆电商革命,颠覆传统购物体验!“

免单优选模式是一种新型的电商销售模式&#xff0c;其核心理念是通过降低商品售价、设置阶梯式奖励以及利用社交关系链&#xff0c;激发消费者购买欲望&#xff0c;实现销售快速增长。 1、合法合规&#xff0c;不存在多层级奖励。 在免单优选模式中&#xff0c;平台不设置多层…

深度学习_8_对Softmax回归的理解

回归问题&#xff0c;例如之前做房子价格预测的线性回归问题 而softmax回归是一个分类问题,即给定一个图片&#xff0c;从猫狗两种动物类别中选出最可靠的那种答案&#xff0c;这个是两类分类问题&#xff0c;因为狗和猫是两类 上述多个输出可以这样理解&#xff0c;假设一个图…

oracle查询数据库内全部的表名、列明、注释、数据类型、长度、精度等

Oracle查询数据库内全部的表名、列明、注释、数据类型、长度、精度 SELECT a.TABLE_NAME 表名, row_number() over(partition by a.TABLE_NAME order by a.COLUMN_NAME desc) 字段顺序,a.COLUMN_NAME 列名, b.COMMENTS 注释,a.DATA_TYPE 数据类型, a.DATA_LENGTH 长度,DATA_SC…

【后端开发】手写一个简单的线程池

半同步半异步线程池 半同步半异步线程池分为三层&#xff1a; 同步服务层 —— 处理来自上层的任务请求&#xff0c;将它们加入到排队层中等待处理。 同步排队层 —— 实际上是一个“同步队列”&#xff0c;允许多线程添加/取出任务&#xff0c;并保证线程安全。 异步服务层…

R语言657中单色colors颜色索引表---全平台可用

R语言657中单色colors颜色索引表—全平台可用

NLP之LSTM与BiLSTM

文章目录 代码展示代码解读双向LSTM介绍&#xff08;BiLSTM&#xff09; 代码展示 import pandas as pd import tensorflow as tf tf.random.set_seed(1) df pd.read_csv("../data/Clothing Reviews.csv") print(df.info())df[Review Text] df[Review Text].astyp…

【计算机网络实验/wireshark】tcp建立和释放

wireshark开始捕获后&#xff0c;浏览器打开xg.swjtu.edu.cn&#xff0c;网页传输完成后&#xff0c;关闭浏览器&#xff0c;然后停止报文捕获。 若捕获不到dns报文&#xff0c;先运行ipconfig/flushdns命令清空dns缓存 DNS报文 设置了筛选条件&#xff1a;dns 查询报文目的…

17、Flink 之Table API: Table API 支持的操作(1)

Flink 系列文章 1、Flink 部署、概念介绍、source、transformation、sink使用示例、四大基石介绍和示例等系列综合文章链接 13、Flink 的table api与sql的基本概念、通用api介绍及入门示例 14、Flink 的table api与sql之数据类型: 内置数据类型以及它们的属性 15、Flink 的ta…