C++学习第五天
创作过程中难免有不足,若您发现本文内容有误,恳请不吝赐教。
一、构造函数
问题1
示例1:
#include<iostream>
using namespace std;class A
{
public:A(int a){cout << "Aint(a)" << endl;_a = a;}
private:int _a;
};class Date
{
public://Date(int year, int month, int day)//{// _year = year;// _month = month;// _day = day;//}
private://内置类型int _year;int _month;int _day;//自定义类型A _aa;
};int main()
{Date d1;
} 
class A没有提供默认构造函数(不用参数就可以调用的构造).
示例2:
#include<iostream>
using namespace std;class A
{
public:A(int a = 0){cout << "A int(a)" << endl;_a = a;}
private:int _a;
};class Date
{
public://Date(int year, int month, int day)//{// _year = year;// _month = month;// _day = day;//}
private://内置类型int _year;int _month;int _day;//自定义类型A _aa;
};int main()
{Date d1;
} ![]()
如果A不提供默认构造,需要使用初始化列表才能解决。当前的学习暂时先通过提供全缺省( A(int a = 0) )来解决这个问题.
简单来说:我们不写编译器生成的默认构造函数,对内置类型不做处理,对自定义类型会调用它的默认构造.
二、默认构造函数
无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。 注意:无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为是默认构造函数。
特点:不传参就可以调用的构造就是默认构造.
三、析构函数

可以简单理解为与构造函数相反的函数,类比Destroy函数.
日期类不需要写析构函数,因为日期类没有资源需要清理,年、月、日属于对象,不需要清理。而像栈这种才需要清理,有指向资源才需要清理。

示例1:
内置类型的成员,不做处理,造成堆上的空间没有释放,造成内存泄漏。
#include<iostream>
using namespace std;typedef int DataType;
class Stack
{
public:Stack(size_t capacity = 3){_array = (DataType*)malloc(sizeof(DataType) * capacity);if (NULL == _array){perror("malloc申请空间失败!!!");return;}_capacity = capacity;_size = 0;}void Push(DataType data){_array[_size] = data;_size++;}/*~Stack(){cout << "~Stack()" << endl;free(_array);_array = nullptr;_size = _capacity = 0;}*/
private:// 内置类型DataType* _array;int _capacity;int _size;};void TestStack()
{Stack s;s.Push(1);s.Push(2);
}int main()
{TestStack();return 0;
}
示例2:
自定义类型的成员,会去调用他的析构。
#include<iostream>
using namespace std;class A
{
public:A(int a = 0){cout << "A(int a)" << endl;_a = a;}~A(){cout << "~A()" << endl;}
private:int _a;
};typedef int DataType;
class Stack
{
public:Stack(size_t capacity = 3){_array = (DataType*)malloc(sizeof(DataType) * capacity);if (NULL == _array){perror("malloc申请空间失败!!!");return;}_capacity = capacity;_size = 0;}void Push(DataType data){_array[_size] = data;_size++;}/*~Stack(){cout << "~Stack()" << endl;free(_array);_array = nullptr;_size = _capacity = 0;}*/
private:// 内置类型DataType* _array;int _capacity;int _size;// 自定义类型A _aa;
};void TestStack()
{Stack s;s.Push(1);s.Push(2);
}int main()
{TestStack();return 0;
}

四、拷贝构造
日期类拷贝:
#include<iostream>
using namespace std;
typedef int DataType;
class Stack
{
public:Stack(size_t capacity = 3){_array = (DataType*)malloc(sizeof(DataType) * capacity);if (NULL == _array){perror("malloc申请空间失败!!!");return;}_capacity = capacity;_size = 0;}void Push(DataType data){_array[_size] = data;_size++;}~Stack(){cout << "~Stack()" << endl;free(_array);_array = nullptr;_size = _capacity = 0;}
private:// 内置类型DataType* _array;int _capacity;int _size;
};class Date
{
public:Date(int year, int month, int day){_year = year;_month = month;_day = day;}void Print(){cout << _year << "/" << _month << "/" << _day << "/" << endl;}
private://内置类型int _year;int _month;int _day;
};void func1(Date d)
{d.Print();
}int main()
{Date d1(2025,1,8);func1(d1);return 0;
}

栈拷贝:
#include<iostream>
using namespace std;
typedef int DataType;
class Stack
{
public:Stack(size_t capacity = 3){_array = (DataType*)malloc(sizeof(DataType) * capacity);if (NULL == _array){perror("malloc申请空间失败!!!");return;}_capacity = capacity;_size = 0;}void Push(DataType data){_array[_size] = data;_size++;}~Stack(){cout << "~Stack()" << endl;free(_array);_array = nullptr;_size = _capacity = 0;}
private:// 内置类型DataType* _array;int _capacity;int _size;
};class Date
{
public:Date(int year, int month, int day){_year = year;_month = month;_day = day;}void Print(){cout << _year << "/" << _month << "/" << _day << "/" << endl;}
private://内置类型int _year;int _month;int _day;
};void func1(Date d)
{d.Print();
}void func2(Stack s)
{}int main()
{Date d1(2025,1,8);func1(d1);Stack s1;func2(s1);return 0;
}


解决方法:
void func2(Stack& s)
{//使用引用
}
拷贝构造函数
定义:只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存
特征1:
拷贝构造函数是构造函数的一个重载形式。
特征2:
拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错, 因为会引发无穷递归调用。
#include<iostream>
using namespace std;class Date
{
public:Date(int year, int month, int day){cout << "Date(Date& d)" << endl;_year = year;_month = month;_day = day;}Date(Date& d){_year = d._year;_month = d._month;_day = d._day;}void Print(){cout << _year << "/" << _month << "/" << _day << "/" << endl;}
private://内置类型int _year;int _month;int _day;
};int main()
{Date d1(2025,1,8);Date d2(d1);return 0;
} ![]()

Date(Date d){//没有引用会引发无穷递归调用_year = d._year;_month = d._month;_day = d._day;} 
#include<iostream>
using namespace std;typedef int DataType;
class Stack
{
public:Stack(size_t capacity = 3){_array = (DataType*)malloc(sizeof(DataType) * capacity);if (NULL == _array){perror("malloc申请空间失败!!!");return;}_capacity = capacity;_size = 0;}Stack(Stack& s){cout << "Stack(Stack& s)" << endl;// 深拷贝_array = (DataType*)malloc(sizeof(DataType) * s._capacity);if (NULL == _array){perror("malloc申请空间失败!!!");return;}memcpy(_array, s._array, sizeof(DataType) * s._size);_size = s._size;_capacity = s._capacity;}void Push(DataType data){_array[_size] = data;_size++;}~Stack(){cout << "~Stack()" << endl;free(_array);_array = nullptr;_size = _capacity = 0;}
private:// 内置类型DataType* _array;int _capacity;int _size;
};void func2(Stack s)
{s.Push(1);
}int main()
{Stack s1;func2(s1);Stack s2(s1);return 0;
} 
问题:
如果不写拷贝构造函数,系统会自动生成吗?
#include<iostream>
using namespace std;class Date
{
public:Date(int year = 1, int month = 1, int day = 1){_year = year;_month = month;_day = day;}void Print(){cout << _year << "/" << _month << "/" << _day << endl;}private:int _year;int _month;int _day;
};typedef int DataType;
class Stack
{
public:Stack(size_t capacity = 3){cout << "Stack()" << endl;_array = (DataType*)malloc(sizeof(DataType) * capacity);if (NULL == _array){perror("malloc申请空间失败!!!");return;}_capacity = capacity;_size = 0;}void Push(DataType data){_array[_size] = data;_size++;}~Stack(){cout << "~Stack()" << endl;free(_array);_array = nullptr;_size = _capacity = 0;}
private:DataType* _array;int _capacity;int _size;
};int main()
{Date d1(2025, 1, 1);Date d2 = d1;Stack st1;Stack st2(st1);return 0;
} 
特征3:
我们不写,编译默认生成的拷贝构造,跟之前的构造函数特性不一样 1、内置类型, 值拷贝
2、自定义的类型,调用他的拷贝
总结:Date不需要我们实现拷贝构造,默认生成就可以用
Stack需要我们自己实现深拷贝的拷贝构造,默认生成会出问题
MyQueue对于默认生成的几个函数非常受用,人生赢家
#include<iostream>
using namespace std;typedef int DataType;
class Stack
{
public:Stack(size_t capacity = 3){cout << "Stack()" << endl;_array = (DataType*)malloc(sizeof(DataType) * capacity);if (NULL == _array){perror("malloc申请空间失败!!!");return;}_capacity = capacity;_size = 0;}Stack(const Stack& s){cout << "Stack(Stack& s)" << endl;// 深拷贝_array = (DataType*)malloc(sizeof(DataType) * s._capacity);if (NULL == _array){perror("malloc申请空间失败!!!");return;}memcpy(_array, s._array, sizeof(DataType) * s._size);_size = s._size;_capacity = s._capacity;}void Push(DataType data){_array[_size] = data;_size++;}~Stack(){cout << "~Stack()" << endl;free(_array);_array = nullptr;_size = _capacity = 0;}
private:DataType* _array;int _capacity;int _size;
};class MyQueue
{
private:Stack _pushst;Stack _popst;
};int main()
{MyQueue mq1;MyQueue mq2 = mq1;return 0;
}
注意:
Date(const Date& d){//一般情况都加上constcout << "Date(Date& d)" << endl;_year = d._year;_month = d._month;_day = d._day;}Date(const Date& d){cout << "Date(Date& d)" << endl;//若不小心写反了,很容易忽视这里的错误d._year = _year ;d._month = _month;d._day = _day;} 五、运算符重载
问题1:
日期对象如何比较大小?能否用 < .
简单的代码实现:
#include<iostream>
using namespace std;class Date
{
public:Date(int year = 1, int month = 1, int day = 1){_year = year;_month = month;_day = day;}void Print(){cout << _year << "/" << _month << "/" << _day << endl;}//private:int _year;int _month;int _day;
};bool DateLess (const Date& x1,const Date& x2)
{if (x1._year < x2._year){return true;}else if (x1._year == x2._year && x1._month < x2._month){return true;}else if (x1._year == x2._year && x1._month == x2._month && x1._day < x2._day){return true;}else{return false;}
}int main()
{Date d1(2025, 1, 1);Date d2(2025, 1, 11);cout<<DateLess(d1, d2)<<endl;return 0;
} ![]()

#include<iostream>
using namespace std;class Date
{
public:Date(int year = 1, int month = 1, int day = 1){_year = year;_month = month;_day = day;}void Print(){cout << _year << "/" << _month << "/" << _day << endl;}//private:int _year;int _month;int _day;
};bool operator<(const Date& x1, const Date& x2)
{if (x1._year < x2._year){return true;}else if (x1._year == x2._year && x1._month < x2._month){return true;}else if (x1._year == x2._year && x1._month == x2._month && x1._day < x2._day){return true;}else{return false;}
}int main()
{Date d1(2025, 1, 1);Date d2(2025, 1, 11);cout << (d1 < d2) << endl;cout << (operator<(d1, d2)) << endl;return 0;
} 
写为成员函数:
// d1 < d2
// d1.operator<(d2)
//操作数顺序不能随便换
bool operator<(const Date& d){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;}} 运算符复用
class Date
{
public:Date(int year = 1, int month = 1, int day = 1){_year = year;_month = month;_day = day;}void Print(){cout << _year << "/" << _month << "/" << _day << endl;}bool operator<(const Date& d){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;}}bool operator==(const Date& d){return _year == d._year&& _month == d._month&& _day == d._day;}// d1 <= d2bool operator<=(const Date& d){return *this < d || *this == d;}bool operator>(const Date& d){return !(*this <= d);}bool operator>=(const Date& d){return !(*this < d);}bool operator!=(const Date& d){return !(*this == d);}
}
实现日期+运算
#include<iostream>
using namespace std;class Date
{
public:Date(int year = 1, int month = 1, int day = 1){_year = year;_month = month;_day = day;}void Print(){cout << _year << "/" << _month << "/" << _day << endl;}int GetMonthDay(int year, int month){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];}//如果写成Date& operator+(int day)会发现Date ret = d1 + 50;中d1也会改变,所以该写成+=Date& operator+=(int day){_day += day;while (_day > GetMonthDay(_year, _month)){// 月进位_day -= GetMonthDay(_year, _month);++_month;// 月满了if (_month == 13){++_year;_month = 1;}}return *this;}Date operator+(int day) //出了作用域对象不在了不能用引用返回{Date tmp(*this);tmp += day;return tmp;//tmp._day += day;//while (tmp._day > GetMonthDay(tmp._year, tmp._month))//{// // 月进位// tmp._day -= GetMonthDay(tmp._year, tmp._month);// ++_month;// // 月满了// if (tmp._month == 13)// {// ++tmp._year;// tmp._month = 1;// }//}//return tmp;}private:// 内置类型int _year;int _month;int _day;
};int main()
{Date d1(2023, 7, 21);Date d2(2022, 8, 21);Date ret = d1 + 50;ret.Print();d1.Print();return 0;
}

总结
以上就是今天要讲的内容,本文仅仅简单介绍了c++的基础知识。
相关文章:
C++学习第五天
创作过程中难免有不足,若您发现本文内容有误,恳请不吝赐教。 提示:以下是本篇文章正文内容,下面案例可供参考 一、构造函数 问题1 关于编译器生成的默认成员函数,很多童鞋会有疑惑:不实现构造函数的情况下…...
openharmony标准系统方案之瑞芯微RK3568移植案例
标准系统方案之瑞芯微RK3568移植案例 本文章是基于瑞芯微RK3568芯片的DAYU200开发板,进行标准系统相关功能的移植,主要包括产品配置添加,内核启动、升级,音频ADM化,Camera,TP,LCD,…...
深入理解 SSH 端口转发:本地 vs 远程 vs 动态转发
🌟 简介 SSH 端口转发(SSH Port Forwarding)作为一种强大而灵活的技术,不仅可以帮助我们安全地访问远程服务,还能轻松突破网络限制。本文将带你深入了解 SSH 端口转发的原理、类型和实战应用。 🌈 目录 &a…...
postman请求参数化
postman界面介绍 一、使用环境变量(Environment Variables)进行参数化 1、在请求中使用环境变量 在请求的url、请求头(Headers)、请求体(Body)等部分都可以使用环境变量。 URL 部分示例 点击 Postman 界面右上角的 “眼睛” 图标(Environment Quick Look)打开环境管理…...
基于 WEB 开发的汽车养护系统设计与实现
标题:基于 WEB 开发的汽车养护系统设计与实现 内容:1.摘要 本文介绍了基于 WEB 开发的汽车养护系统的设计与实现。文章首先阐述了系统的背景和目的,即随着汽车保有量的增加,汽车养护需求日益增长,传统的汽车养护方式已经无法满足人们的需求&…...
Nginx正向代理配置
Nginx 正向代理默认只支持 http 协议,不支持 https 协议,需借助 "ngx_http_proxy_connect_module" 模块实现 https 正向代理,详情请参考: https://github.com/chobits/ngx_http_proxy_connect_module 安装Nginx某些模块…...
本地仓库管理之当前分支内的操作
以刚搭建好的git仓库为例,刚搭建完的仓库只有master分支,使用git branch查看当前的分支情况。 elfubuntu:~/work/example/hello$ git branch *所在分支为当前分支,即master分支 当前分支进行源码修改时简单流程图如下: 在当前分…...
《内网穿透:网络拓展与安全防护的平衡艺术》
一、引言:开启内网穿透的大门 在当今数字化浪潮席卷全球的时代,网络已成为人们生活和工作中不可或缺的一部分。我们日常使用的网络,如同一个庞大而复杂的生态系统,其中内网和外网犹如两个相互关联却又有所区别的世界。 想象一下…...
【python写个可以运行的2048小游戏】
写一个完整的2048小游戏在Python中是一个相对复杂的任务,因为它涉及到用户界面、事件处理、游戏逻辑等多个方面。为了简化这个过程,我们可以使用Python的图形库,比如pygame。下面是一个简单的2048游戏的实现。 首先,确保你已经安…...
【Flink系列】9. Flink容错机制
9. 容错机制 在Flink中,有一套完整的容错机制来保证故障后的恢复,其中最重要的就是检查点。 9.1 检查点(Checkpoint) 9.1.1 检查点的保存 1)周期性的触发保存 “随时存档”确实恢复起来方便,可是需要我…...
DETR论文阅读
1. 动机 传统的目标检测任务需要大量的人工先验知识,例如预定义的先验anchor,NMS后处理策略等。这些人工先验知识引入了很多人为因素,且较难处理。如果能够端到端到直接生成目标检测结果,将会使问题变得很优雅。 2. 主要贡献 提…...
关于vite+vue3+ts项目中env.d.ts 文件详解
env.d.ts 文件是 Vite 项目中用于定义全局类型声明的 TypeScript 文件。它帮助开发者向 TypeScript提供全局的类型提示,特别是在使用一些特定于 Vite 的功能时(如 import.meta.env)。以下是详细讲解及代码示例 文章目录 **1. env.d.ts 文件的…...
如何优化Elasticsearch大文档查询?
记录一次业务复杂场景下DSL优化的过程 背景 B端商城业务有一个场景就是客户可见的产品列表是需要N多闸口及各种其它逻辑组合过滤的,各种闸口数据及产品数据都是存储在ES的(有的是独立索引,有的是作为产品属性存储在产品文档上)。 在实际使用的过程中&a…...
Kotlin Bytedeco OpenCV 图像图像54 透视变换 图像矫正
Kotlin Bytedeco OpenCV 图像图像54 透视变换 图像矫正 1 添加依赖2 测试代码3 测试结果 在OpenCV中,仿射变换(Affine Transformation)和透视变换(Perspective Transformation)是两种常用的图像几何变换方法。 变换方…...
Linux中DataX使用第一期
简介 DataX 是阿里云 DataWorks数据集成 的开源版本,在阿里巴巴集团内被广泛使用的离线数据同步工具/平台。DataX 实现了包括 MySQL、Oracle、OceanBase、SqlServer、Postgre、HDFS、Hive、ADS、HBase、TableStore(OTS)、MaxCompute(ODPS)、Hologres、DRDS, databen…...
[Qt]事件-鼠标事件、键盘事件、定时器事件、窗口改变事件、事件分发器与事件过滤器
目录 前言:Qt与操作系统的关系 一、Qt事件 1.事件介绍 2.事件的表现形式 常见的Qt事件: 常见的事件描述: 3.事件的处理方式 处理鼠标进入和离开事件案例 控件添加到对象树底层原理 二、鼠标事件 1.鼠标按下和释放事件(单击&#x…...
关于机器学习的一份总结
在之前的文章中分别有详细的关于机器学习中某一学习算法的介绍,但缺少一个总体关于机器学习的总结,所以在这篇文中就是关于机器学习的一份总结。 在最近的日子中,人工智能日益火热起来,而机器学习是其中举足轻重的一部分…...
推荐一个开源的轻量级任务调度器!TaskScheduler!
大家好,我是麦鸽。 这次推荐一款轻量级的嵌入式任务调度器,目前已经有1.4K的star,这个项目比较轻量化,只有5个源文件,可以作为学习的一个开源项目。 核心文件 项目概述: 这是一个轻量级的协作式多任务处理&…...
【18】Word:明华中学-儿童医保❗
目录 题目 NO2 NO3 NO4 NO5 NO6 NO7 NO8 NO9 题目 NO2 布局→页面设置对话框→纸张方向:横向→纸张大小:A3 ;页面设置对话框:直接输入纸张大小的宽度和高度即可→页面设置对话框:上下左右边距→版式&…...
如何用selenium来链接并打开比特浏览器进行自动化操作(1)
前言 本文是该专栏的第76篇,后面会持续分享python爬虫干货知识,记得关注。 本文,笔者将基于“比特浏览器”,通过selenium来实现链接并打开比特浏览器,进行相关的“自动化”操作。 值得一提的是,在本专栏之前,笔者有详细介绍过“使用selenium或者pyppeteer(puppeteer)…...
JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...
Vue记事本应用实现教程
文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展:显示创建时间8. 功能扩展:记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...
VB.net复制Ntag213卡写入UID
本示例使用的发卡器:https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...
如何在看板中体现优先级变化
在看板中有效体现优先级变化的关键措施包括:采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中,设置任务排序规则尤其重要,因为它让看板视觉上直观地体…...
[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?
论文网址:pdf 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔记,谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...
C++.OpenGL (10/64)基础光照(Basic Lighting)
基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...
Spring AI 入门:Java 开发者的生成式 AI 实践之路
一、Spring AI 简介 在人工智能技术快速迭代的今天,Spring AI 作为 Spring 生态系统的新生力量,正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务(如 OpenAI、Anthropic)的无缝对接&…...
中医有效性探讨
文章目录 西医是如何发展到以生物化学为药理基础的现代医学?传统医学奠基期(远古 - 17 世纪)近代医学转型期(17 世纪 - 19 世纪末)现代医学成熟期(20世纪至今) 中医的源远流长和一脉相承远古至…...
iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈
在日常iOS开发过程中,性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期,开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发,但背后往往隐藏着系统资源调度不当…...
MySQL:分区的基本使用
目录 一、什么是分区二、有什么作用三、分类四、创建分区五、删除分区 一、什么是分区 MySQL 分区(Partitioning)是一种将单张表的数据逻辑上拆分成多个物理部分的技术。这些物理部分(分区)可以独立存储、管理和优化,…...
