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

【C++打怪之路Lv4】-- 类和对象(中)

🌈 个人主页:白子寰
🔥 分类专栏:C++打怪之路,python从入门到精通,数据结构,C语言,C语言题集👈 希望得到您的订阅和支持~
💡 坚持创作博文(平均质量分82+),分享更多关于深度学习、C/C++,python领域的优质内容!(希望得到您的关注~)

目录

类的6个默认成员函数

构造函数

概念 

六个特性

默认构造函数的意义

 析构函数

概念

四个特性

小结

 拷贝构造函数

概念

三个特性

总结

 赋值运算符重载

运算符重载

相等操作符重载函数(比较Date中的两个对象是否相等) 

在全局中

在类中

注意点

this 和 *this 的区别

​编辑

赋值运算符重载

赋值运算符重载格式

 注意点

赋值运算符重载 和 拷贝构造函数 的区别

 传值返回 和 传引用返回 的区别

前置++ 和 后置++ 重载

const成员

含义

在哪用

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

日期类的实现

Date.h

Date.cpp

Test.cpp


类的6个默认成员函数

1、特殊成员函数

2、不写编译器会自动生成



构造函数

概念 

构造函数是初始化对象不是开空间

C语言中没有初始化,会出现随机值


六个特性

  1. 函数名与类名相同
  2. 无返回值

  3. 对象实例化 自动调用 该函数

  4. 构造函数可以重载

  5. 如没有显式定义的构造函数,编译器自动生成(隐式的无参构造函数);反之,则不会自动生成

  • 注:①不显式写默认构造,对于内置类型成员变量,看编译器是否处理; 对于自定义类型成员变量才会调用它的 无参构造(不传参就可以调用的那个构造)

②默认构造函数包括:无参构造函数、全缺省构造函数、编译器默认生成的构造函数(隐式的无参构造函数)

6、内置类型成员变量在类中声明时可以给默认值

 


默认构造函数的意义

在两个栈实现一个队列,编译器给了初始化(在某种情况下有意义)




 析构函数

概念

对象销毁时自动调用析构函数,完成对象中的资源清理

C语言没有写Destroy,会造成内存泄漏


四个特性

  1. 析构函数名在类名前加~
  2. 无参数无返回值
  3. 一个类只能析构一个函数,析构函数不能重载
  4. 在生命周期结束时自动调用
  • 析构函数内置类型不做处理自定义类型调用它的析构
  • 析构函数可以显式写

 


小结

  1. 有资源清理(开空间)才需要析构函数;如Stack、Queue
  2. 有两种场景不需要显式析构,用默认生成的就OK了
  • ①没有资源清理,如Date
  • ②内置类型成员没有资源需要清理,剩下的都是自定义类型成员;如MyQueue



 拷贝构造函数

概念

用同类型的对象拷贝初始化


三个特性

  1. 拷贝构造函数是构造函数的一个重载形式
  2. 拷贝构造函数的参数只有一个且必须是类类对象的引用,使用传值方式编译器直接报错,会引发无穷递归
  3. 未显式定义,编译器会默认生成拷贝构造函数


总结

  1. 一般情况下,不需要显式写析构函数,就不用写拷贝构造函数(值拷贝)
  2. 如果 内部有指针 或者 一些值指向资源,需要显式写析构函数释放,需要写构造完成深拷贝; 如Satck、Queue、List




 赋值运算符重载

运算符重载


相等操作符重载函数(比较Date中的两个对象是否相等) 

在全局中

全局中写 operator== 函数,要屏蔽 Date类 中private

那封装性如何保证?友元 重载成员函数 解决

这里讲的是重载成员函数,把 内置类型成员 公有,这样在全局中函数就能 访问 内置类型成员

在类中

注意点

在主函数中


this 和 *this 的区别

赋值运算符重载

赋值运算符重载格式


 注意点


赋值运算符重载 和 拷贝构造函数 的区别


 传值返回 和 传引用返回 的区别

传值返回 会生成当前对象的一个拷贝,拷贝一个临时对象
引用返回 生成某别名,出了作用域就销毁了
总结 虽然引用返回减少了拷贝,但出了函数作用域,返回对象还在才能用引用(在静态)


前置++ 和 后置++ 重载




const成员

含义

const修饰的是*this,本质上是改变this的类型

在哪用

  1. 运算符重载
  2. 不改变自身

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

不显式实现,编译器默认生成




日期类的实现

Date.h

#pragma once#include<iostream>
#include<stdlib.h>
using namespace std;class Date
{// 友元函数,可以访问私有friend ostream& operator<<(ostream& out, const Date& d);friend istream& operator>>(istream& in, Date& d);public:// 构造函数Date(int year, int month, int day);// 打印void Print();// 运算符重载// 实现</>,==就可以了,其他的复用(要建立栈帧,内联,不能声明和定义分离,在类里面定义就是内联)bool operator==(const Date& d) const;bool operator!=(const Date& d) const;bool operator>(const Date& d) const;bool operator>=(const Date& d) const;bool operator<(const Date& d) const;bool operator<=(const Date& d) const;static int GetMonthDay(int year, int month){int GetMonthDayArr[] = { 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;}else return GetMonthDayArr[month];}// 检查日期是否正确bool checkDate(){if (_month < 1 || _month > 12 || _day <= 0 || _day > GetMonthDay(_year, _month)) return false;else return true;}// 日期 + 天数Date& operator+=(int day);Date operator+(int day) const;// 日期 - 天数Date& operator-=(int day);Date operator-(int day) const;// 前置++Date& operator++();// 后置++Date operator++(int) const;// 前置--Date& operator--();// 后置--Date operator--(int) const;// d1 - d2int operator-(const Date& d) const;private:int _year;int _month;int _day;
};// 流插入重载
ostream& operator<<(ostream& out, const Date& d);
// 流提取重载
istream& operator>>(istream& in, Date& d);

Date.cpp

#define _CRT_SECURE_NO_WARNINGS 1#define _CRT_SECURE_NO_WARNINGS 1#include"Date.h"Date::Date(int year, int month, int day)
{//cout << "Date(int year, int month, int day)" << endl;_year = year;_month = month;_day = day;
}void Date::Print()
{cout << _year << "-" << _month << "-" << _day << endl;
}bool Date::operator==(const Date& d) const
{return 	this->_year == d._year&& this->_month == d._month&& this->_day == d._day;
}bool Date::operator!=(const Date& d) const
{return !(*this == d);
}bool Date::operator>(const Date& d) const
{if (this->_year > d._year) return true;else if (this->_year == d._year && this->_month > d._month) return true;else if (this->_year == d._year && this->_month == d._month && this->_day > d._day) return true;return false;
}bool Date::operator>=(const Date& d) const
{return *this > d || *this == d;
}bool Date::operator<(const Date& d) const
{return !(*this >= d);
}bool Date::operator<=(const Date& d) const
{return !(*this > d);
}// 日期 + 天数
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;
}Date& Date::operator-=(int day)
{if (day < 0) return *this += -day;_day -= day;while (_day <= 0){--_month;if (_month == 0){_month = 12;--_year;}_day += GetMonthDay(_year, _month);}return *this;
}Date Date::operator-(int day) const
{Date tmp = *this;tmp -= day;return tmp;
}// 前置++
Date& Date::operator++()
{*this += 1;return *this;
}// 后置++
Date Date::operator++(int) const
{Date tmp = *this;tmp += 1;return tmp;
}// 前置--
Date& Date::operator--()
{*this -= 1;return *this;
}// 后置--
Date Date::operator--(int) const
{Date tmp = *this;tmp -= 1;return tmp;
}int Date::operator-(const Date& d) const
{Date max = *this;Date min = d;int n = 0, flag = 1;if (*this < d){max = d;min = *this;flag = -1;}while (min != max){++min;++n;}return flag * n;
}//ostream& Date::operator<<(ostream& out)
//{
//	out << _year << "-" << _month << "-" << _day << endl;
//	return out;
//}ostream& operator<<(ostream& out, const Date& d)
{out << d._year << "-" << d._month << "-" << d._day << endl;return out;
}istream& operator>>(istream& in, Date& d)
{cout << "请输入年、月、日:";in >> d._year >> d._month >> d._day;if (!d.checkDate()) {cout << "输入的日期无效,请重新输入。" << endl;in.clear(); // 清除错误标志in.ignore(numeric_limits<streamsize>::max(), '\n'); // 忽略错误输入直到下一个换行符return in;}return in;
}

Test.cpp

#define _CRT_SECURE_NO_WARNINGS 1#include"Date.h"
void test1()
{Date d1(2024, 9, 26);Date d2(2024, 9, 26);bool ret1 = d1 > d2;bool ret2 = d1 >= d2;bool ret3 = d1 < d2;bool ret4 = d1 <= d2;bool ret5 = d1 == d2;bool ret6 = d1 != d2;cout << ret1 << endl;cout << ret2 << endl;cout << ret3 << endl;cout << ret4 << endl;cout << ret5 << endl;cout << ret6 << endl;
}void test2()
{Date d1(2024, 9, 26);Date d2(2024, 9, 26);// +=	// 11-15Date tmp = d1 -= -100;d1.Print();//tmp.Print();+ //Date tmp2 = d2 + 50;//d2.Print();		// 9-26//tmp2.Print();	// 11-15//Date d3(2024, 9, 26);//Date d4(2024, 9, 26);-=	//8-7//Date tmp3 = d3 -= 50;//d3.Print();//tmp3.Print();- //Date tmp4 = d4 - 50;//d4.Print();//tmp4.Print();
}void test3()
{Date d1(2024, 9, 26);Date d2(2024, 9, 26);Date tmp = --d1;d1.Print();tmp.Print();Date tmp2 = d2--;d2.Print();tmp2.Print();
}void test4()
{Date d1(2024, 9, 26);Date d2(2024, 10, 1);int ret = d1 - d2;cout << ret << endl;
}void test5()
{// 流插入和流提取 / 内置类型 直接用,为什么?//cout << "1";//printf("2");//cout << "3";//printf("4");Date d1(2024, 9, 26);//d1 << cout;	// 类中cout << d1;		// 全局
}void test6()
{Date d1(2024,9,27);Date d2(2024,10,1);cin >> d1 >> d2;cout << d1 << d2;
}void test7()
{const Date d1(2024, 9, 27);Date d2(2024, 9, 27);bool d3 = d1 > d2;Date d4 = d1 - 10;
}int main()
{//test1();//test2();//test3();//test4();//test5();//test6();test7();
}



 

 ***********************************************************分割线*****************************************************************************
完结!!!
感谢浏览和阅读。

等等等等一下,分享最近喜欢的一句话:

“我从来没有后悔对任何人好,哪怕看错人,哪怕被辜负,哪怕撞南墙,因为我对你好不代表你有多好,只是因为,我很好!”。

我是白子寰,如果你喜欢我的作品,不妨你留个点赞+关注让我知道你曾来过。
你的点赞和关注是我持续写作的动力!!! 
好了划走吧。

相关文章:

  • Find My汽车钥匙|苹果Find My技术与钥匙结合,智能防丢,全球定位
  • 介绍篇| 爬虫工具介绍
  • 墙绘交易平台:SpringBoot框架的设计与实现
  • Redis缓存淘汰算法详解
  • Mac优化清理工具CleanMyMac X 4.15.6 for mac中文版
  • 《OpenCV 计算机视觉》—— 视频背景建模
  • 基于STM32+4G通信技术设计远程农田灌溉系统(236)
  • Python空间地表联动贝叶斯地震风险计算模型
  • 前端工程规范-5:Git提交信息规范(commitlint + czg)
  • AWS Redshift把老用户权限赋予新用户
  • 计算机毕业设计 基于爬虫与文本挖掘的网络舆情监控系统的设计与实现 Python+Django+Vue 前后端分离 附源码 讲解 文档
  • \?拉普拉斯到底在讲什么\?控制理论\?倒立摆/
  • 如何选择与运用工具提升工作效率的秘密指南
  • 【自动化测试】Appium Server如何安装和Appium Server安装困难的原因和解决方法以及常见的一些安装失败的错误和解决方法
  • FFmpeg源码:avio_seek函数分析
  • 【JavaScript】通过闭包创建具有私有属性的实例对象
  • 【跃迁之路】【519天】程序员高效学习方法论探索系列(实验阶段276-2018.07.09)...
  • CentOS7简单部署NFS
  • ECMAScript6(0):ES6简明参考手册
  • Java程序员幽默爆笑锦集
  • js递归,无限分级树形折叠菜单
  • NSTimer学习笔记
  • opencv python Meanshift 和 Camshift
  • Python 基础起步 (十) 什么叫函数?
  • Python学习之路16-使用API
  • Python中eval与exec的使用及区别
  • ucore操作系统实验笔记 - 重新理解中断
  • vue从创建到完整的饿了么(11)组件的使用(svg图标及watch的简单使用)
  • Web标准制定过程
  • 基于Javascript, Springboot的管理系统报表查询页面代码设计
  • 聊聊sentinel的DegradeSlot
  • 前端每日实战:61# 视频演示如何用纯 CSS 创作一只咖啡壶
  • 使用common-codec进行md5加密
  • 一些css基础学习笔记
  • 怎样选择前端框架
  • media数据库操作,可以进行增删改查,实现回收站,隐私照片功能 SharedPreferences存储地址:
  • ionic入门之数据绑定显示-1
  • # 飞书APP集成平台-数字化落地
  • #VERDI# 关于如何查看FSM状态机的方法
  • $.type 怎么精确判断对象类型的 --(源码学习2)
  • (11)MATLAB PCA+SVM 人脸识别
  • (23)mysql中mysqldump备份数据库
  • (Charles)如何抓取手机http的报文
  • (附源码)ssm基于web技术的医务志愿者管理系统 毕业设计 100910
  • (六)激光线扫描-三维重建
  • (亲测成功)在centos7.5上安装kvm,通过VNC远程连接并创建多台ubuntu虚拟机(ubuntu server版本)...
  • (译)计算距离、方位和更多经纬度之间的点
  • (自适应手机端)响应式新闻博客知识类pbootcms网站模板 自媒体运营博客网站源码下载
  • .env.development、.env.production、.env.staging
  • .naturalWidth 和naturalHeight属性,
  • .NET : 在VS2008中计算代码度量值
  • .NET Core Web APi类库如何内嵌运行?
  • .NET 使用 ILRepack 合并多个程序集(替代 ILMerge),避免引入额外的依赖
  • .Net6使用WebSocket与前端进行通信
  • .net开发时的诡异问题,button的onclick事件无效