类和对象【C++】【中篇】
目录
一、类的6个默认成员函数
1、构造函数
2、析构函数
3、拷贝构造函数
4、赋值重载函数
二、赋值运算符重载
一、类的6个默认成员函数
注意:默认成员函数不能在类外面定义成全局函数。因为类里没有的话会自动生成,就会产生冲突。
1、构造函数
对于下面这个程序,可以看到,每次创建对象时,我们都需要手动调用Init函数,这样是不是有些麻烦呢?
class Date
{
public:void Init(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;
};
int main()
{Date d1;d1.Init(2023, 5, 1);d1.Print();Date d2;d2.Init(2023, 5, 2);d2.Print();return 0;
}
构造函数就可以很好地解决这个问题。
构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象是由编译器自动调用,以保证每个成员都有一个合适的初始值,并且在对象整个生命周期只调用一次。
其主要任务并不是开空间创建对象,而是初始化对象。
特征:
1、函数名与类名相同。
2、无返回值。(也不需要void)
3、对象实例化时编译器会自动调用对应的构造函数。
4、构造函数可以重载。
使用举例:
class Date
{
public://无参构造函数Date(){}//带参构造函数Date(int year, int month, int day){_year = year;_month = month;_day = day;}
private:int _year;int _month;int _day;
};
int main()
{Date d1;//调用无参构造函数Date d2(2023, 5, 8);//调用有参的构造函数return 0;
}
注意:
1、如果通过无参构造函数创建对象时,对象后不用跟括号,否则就成了函数声明。
2、如果类中没有显示定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦用户显示定义,编译器将不再生成。
3、编译器自动生成的默认构造函数,对内置类型不做处理(有些编译器可能会),对自定义类型成员则会调用它的默认构造。
一般情况下,有内置类型时,就需要自己写构造函数,如果全是自定义类型成员,就可以考虑让编译器自己生成。
在C++11中针对内置类型成员不初始化的缺陷,又打了补丁,即,内置类型成员变量在类中声明时可以给默认值。
4、无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。注意:无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为是默认构造函数。
2、析构函数
(1)概念
析构函数:是特殊的成员函数。与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象的销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成对象中的资源管理。
(2)特性
1、析构函数名是在类名前加 ~
2、无参数无返回类型
3、一个类只能有一个析构函数,若未显示定义,系统自动生成默认的析构函数。
4、析构函数不能重载
5、对象生命周期结束时,C++编译系统自动调用析构函数。
1、一般情况下,有动态申请资源,就需要显示写析构函数释放资源
2、没有动态申请的资源,就不需要写析构
3、如果需要释放的资源的成员类型都是自定义类型,则不需要写析构
3、拷贝构造函数
(1)概念
拷贝构造函数:是特殊的成员函数,只有单个形参,该形参是对本类类型对象的引用(一般用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。
(2)特征
1、拷贝构造函数是构造函数的一个重载形式。
2、拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器会直接报错因为会引发无穷递归调用。
3、若未显示定义,编译器会生成默认的拷贝构造函数。默认拷贝构造函数对象按内存存储按字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝。
class Date
{
public:Date(int year=1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}Date(const Date& d){//this->_year = d._year;(d2的_year = d1的_year)_year = d._year;_month = d._month;_day = d._day;}
private:int _year;int _month;int _day;
};
int main()
{Date d1;Date d2(d1);return 0;
}
4、赋值重载函数
d1=d2;//d1.operator =(d2);
已经存在的两个对象之间复制拷贝。
注意:与拷贝构造函数不同的是,拷贝构造函数是用一个对象初始化另一个对象
下面这个关于日期类的赋值重载函数有没有什么问题?
void operator =(const Date& d){_year = d._year;_month = d._month;_day = d._day;}
int main()
{Date d1(2023, 5, 8);//带参构造函数Date d2(d1);//拷贝构造函数,用一个已经存在的对象初始化另一个对象Date d3(d2);//拷贝构造函数//将d2赋值给d1,已经存在的两个对象的拷贝复制d1 = d2 = d3;return 0;
}
在赋值时,如果是连续赋值,上面的函数就会有问题。
d1=d2=d3;
d3赋值给了d2后,应该有一个返回值,而我们上面写的函数的返回值是空。
Date operator =(const Date& d){_year = d._year;_month = d._month;_day = d._day;return *this;//传值返回,返回的是对象的拷贝,不好}
如果像上面这样写,是传值返回,就需要再调用拷贝构造函数
因此,为了提高效率,我们可以将返回值改为引用。
Date& operator =(const Date& d){_year = d._year;_month = d._month;_day = d._day;return *this;//因为出了作用域*this还在,所以可以用引用返回。}
上面的代码对于d1=d1;这样的代码是可以编译通过的,如果不想,可以按照如下写法:
Date& operator =(const Date& d){if(*this != &d){_year = d._year;_month = d._month;_day = d._day;} return *this;//因为出了作用域*this还在,所以可以用引用返回。}
默认生成的赋值重载函数跟拷贝构造一样:
1、内置类型成员:值拷贝/浅拷贝。
2、自定义类型成员会去调用它的赋值重载函数。
二、赋值运算符重载
C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。
函数名字:关键字operator后面接需要重载的运算符符号。
函数原型:返回值类型operator操作符(参数列表)
注意:
(1)不能通过其他连接符号来创建新的操作符。
(2)重载操作符必须有一个类类型参数。
(3)用于内置类型的运算符,其含义不能改变,如+
(4)作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏的this
(5)(.*)(::)(sizeof)(?:)(.)注意以上5个运算符不能重载,笔试选择题中经常出现。
class Date
{
public:void Init(int year, int month, int day){_year = year;_month = month;_day = day;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}//bool operator == (Date* this,const Date& d2)bool operator ==(const Date& d2){return _year == d2._year && _month == d2._month && _day == d2._day;}
private:int _year;int _month;int _day;
};
int main()
{Date d1, d2;d1.Init(2023, 5, 1);d2.Init(2023, 5, 2);if (d1 == d2){printf("相等");}else{printf("不相等");}return 0;
}
三、日期类的实现
#include <iostream>
#include <functional>
#include<cassert>
using namespace std;
class Date
{//友元函数friend ostream& operator<<(ostream& out, const Date& d);friend istream& operator>>(istream& in, Date& d);public:Date(int year = 1, int month = 1, int day = 1);//带参构造函数//如果这样写://1、Date d1(2023, 5, 1);//2、const Date d2(2004, 3, 5);//d1.Print(Date* this);//可以//不可以,因为从const Date*this到Date *this权限放大了//d2.Print(Date* this);//void Print()//{// cout << _year << "-" << _month << "-" << _day << endl;//}//如果将Print的参数改成const Date *this//对于1来说是权限缩小,对于2来说是平移,都是允许的//只要不改变对象成员变量的函数都应该const,这样const对象和普通对象就都可以调用了void Print()const{cout << _year << "-" << _month << "-" << _day << endl;}bool operator <(const Date& x);bool operator >(const Date& x);bool operator ==(const Date& x);bool operator <= (const Date& x);bool operator >= (const Date& x);bool operator !=(const Date& x);int GetMonthDay(int year, int month);Date& operator += (int day);Date operator + (int day);Date& operator++();Date operator++(int);//后置++Date& operator -= (int day);Date& operator - (int day);Date& operator--();Date operator--(int);//后置++int operator-(const Date& x);
private:int _year;int _month;int _day;
};
#include"Date.h"
Date::Date(int year, int month, int day)//带参构造函数
{if (year > 0 && month > 0 && month < 13 && day>0 && day <= GetMonthDay(year, month)){_year = year;_month = month;_day = day;}else{cout << "日期非法" << endl;assert(false);}
}
bool Date::operator <(const Date& x)
{if (_year < x._year)return true;else if (_year == x._year && _month < x._month)return true;else if (_year == x._year && _month == x._month && _day < x._day)return true;else return false;
}
bool Date :: operator ==(const Date& x)
{return _year == x._year && _month == x._month && _day == x._day;
}
bool Date:: operator <= (const Date& x)
{return *this < x || *this == x;
}
bool Date :: operator >(const Date& x)
{return !(*this <= x);
}
bool Date :: operator >= (const Date& x)
{return *this > x || *this == x;
}
bool Date :: operator!=(const Date& x)
{return !(*this == x);
}int Date::GetMonthDay(int year, int month)
{int daysArr[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 daysArr[month];
}
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)
{Date tmp(*this);tmp += day;return tmp;
}
Date& Date :: operator++()//前置++
{*this += 1;return *this;
}
Date Date::operator++(int)//后置++
{Date tmp(*this);*this += 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)
{Date tmp(*this);tmp -= day;return tmp;
}Date& Date:: operator--()
{*this -= 1;return *this;
}
Date Date:: operator--(int)//后置++
{Date tmp(*this);*this -= 1;return tmp;
}
int Date:: operator-(const Date& x)
{Date max = *this;Date min = x;int flag = 1;if (*this<x){max = x;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;
}
相关文章:

类和对象【C++】【中篇】
目录 一、类的6个默认成员函数 1、构造函数 2、析构函数 3、拷贝构造函数 4、赋值重载函数 二、赋值运算符重载 一、类的6个默认成员函数 注意:默认成员函数不能在类外面定义成全局函数。因为类里没有的话会自动生成,就会产生冲突。 1、构造函数…...

2.SpringBoot运维实用篇
SpringBoot运维实用篇 基础篇发布以后,看到了很多小伙伴在网上的留言,也帮助超过100位小伙伴解决了一些遇到的问题,并且已经发现了部分问题具有典型性,预计将有些问题在后面篇章的合适位置添加到本套课程中,作为解…...
【c++】浅讲引用
【c】浅讲引用 前言引用定义作用做输出型参数引用作返回值总结 关于引用的权限 结尾 前言 博主开始细学c和linux了 这次就带来浅学了的引用。 引用 定义 引用不是在内存中开辟一个新空间的新变量 类似于给变量取别名,和取别名的对象在空间中公用一个对象 例&#…...
CSS布局基础(文字[行内<块>]与行内[块]垂直对齐方式 文字溢出显示省略号)
文字[行内<块>]与行内[块]垂直对齐方式 文字[行内<块>]与行内[块]垂直对齐方式概述图片底部空隙问题 文字溢出显示省略号单行文字多行文字 文字[行内<块>]与行内[块]垂直对齐方式 概述 vertical-align: top | middle| bottom | baseline(默认) | sub | sup…...

AI自动写文章_免费在线原创文章生成器
自动写文章生成器 自动写文章生成器是一种利用人工智能和自然语言处理技术,帮助用户快速生成文章的工具。该软件可以根据用户的需求和选择,自动生成符合要求的文章,无需手动编写和修改。 自动写文章生成器的主要功能包括以下几个方面&#…...

Java阶段二Day15
Java阶段二Day15 文章目录 Java阶段二Day15复习前日知识点对象数据类型注入数组类型注入集合类型的注入p命名空间引入外部属性文件 基于XML管理beanbean的作用域bean的生命周期代码演示生命周期后置处理器处理展示基于XML的自动装配 基于注解管理bean开启组件扫描使用注解定义B…...

从月薪3000到月薪20000,自动化测试应该这样学...
绝大多数测试工程师都是从功能测试做起的,工作忙忙碌碌,每天在各种业务需求学习和点点中度过,过了好多年发现自己还只是一个功能测试工程师。 随着移动互联网的发展,从业人员能力的整体进步,软件测试需要具备的能力要…...
Python魔法方法 单例模式
前言 本文介绍一下python中常用的魔法方法以及面向对象中非常重要的单例模式。 魔法方法 python中一切皆对象,因为python是面向对象的编程语言。python给类和对象提供了大量的内置方法,这些内置方法也称魔法方法。这些魔法方法总是在某种条件下自动触…...

计算机网络基础知识(三)—— 什么是OSI七层模型?
文章目录 00 | 🛸发展史🛸01 | 🛸OSI七层参考模型🛸02 | 🛸OSI七层参考模型的信息流向🛸 OSI七层模型是Open Systems Interconnection Reference Model的缩写,是由国际标准化组织(IS…...
Python(符号计算常微分方程)谐振子牛顿运动方程
牛顿运动方程 牛顿运动方程可以写成以下形式 F d p d t m d v d t m d 2 r d t 2 \mathbf{F}\frac{d \mathbf{p}}{d t}m \frac{d \mathbf{v}}{d t}m \frac{d^2 \mathbf{r}}{d t^2} Fdtdpmdtdvmdt2d2r 恒力问题 具有恒定力的问题意味着恒定的加速度。 典型的例子是…...

OpenCL编程指南-1.2OpenCL基本概念
OpenCL概念基础 面向异构平台的应用都必须完成以下步骤: 1)发现构成异构系统的组件。 2)探查这些组件的特征,使软件能够适应不同硬件单元的特定特性。 3)创建将在平台上运行的指令块(内核)。 4)…...

使用 ChatGPT 辅助学习——为自己找一个老师
我们每个人都有许多标签,例如高中生、成绩中等、文科,根据这些标签我和其他拥有相同标签的人分配了相同的教程、班级和老师,这可以带来效率上的提升,因为同一份教程、老师就可以服务几十上百人,而无须为每个人定制&…...
MySQL基础(二十一)用户与权限管理
1. 用户管理 1.1 登录MySQL服务器 启动MySQL服务后,可以通过mysql命令来登录MySQL服务器,命令如下: mysql –h hostname|hostIP –P port –u username –p DatabaseName –e "SQL语句"-h参数后面接主机名或者主机IP,…...

程序员的下一个风口
面对近一年的裁员潮,以及 GPT 出现带来的 AI 颠覆潮流,各种话题出现:「前端已死」、「后端已死」、「Copy/Paste 程序员将被 AI 取代」。程序员行业是否还有发展空间? 这一两年的就业机会是因为经济衰落周期内造成的,不…...

Android 自定义View 之 简易输入框
简易输入框 前言正文① 构造方法② XML样式③ 测量④ 绘制1. 绘制方框2. 绘制文字 ⑤ 输入1. 键盘布局2. 键盘接口3. 键盘弹窗4. 显示键盘5. 相关API 四、使用自定义View五、源码 前言 在日常工作开发中,我们时长会遇到各种各样的需求,不部分需求是可以通…...

SpringMVC的基础知识
创建SpringMVC项目 SpringMVC项目其实和SpingBoot项目差不多,就多引入了一个SpringWeb项目而已拉 可以看这篇博客,创建的就是一个SpringMVC项目--创建项目の博客 SpringMVC是啥 Spring是啥相信大家都了解 啥是MVC呢?MVC是Model View Controller的缩写 我们分开看这三个词Model…...

OpenPCDet系列 | 4.2 DataAugmentor点云数据增强模块解析
文章目录 DataAugmentor模块解析1. gt_sampling2. random_world_flip3. random_world_rotation4. random_world_scaling5. limit_period DataAugmentor模块解析 在pointpillars算法中,具体的数据增强方法配置是在yaml中的DATA_CONFIG.DATA_AUGMENTOR进行配置&#…...

精准测试之过程与实践 | 京东云技术团队
作者:京东工业 宛煜昕 一、怎样的技术 •百度百科: 精准测试是一套计算机测试辅助分析系统。 精准测试的核心组件包含的软件测试示波器、用例和代码的双向追溯、智能回归测试用例选取、覆盖率分析、缺陷定位、测试用例聚类分析、测试用例自动生成系统…...
类ChatGPT逐行代码解读(1/2):从零实现Transformer、ChatGLM-6B
前言 最近一直在做类ChatGPT项目的部署 微调,关注比较多的是两个:一个LLaMA,一个ChatGLM,会发现有不少模型是基于这两个模型去做微调的,说到微调,那具体怎么微调呢,因此又详细了解了一下微调代…...

车道线检测
前言 目前,车道线检测技术已经相当成熟,主要应用在自动驾驶、智能交通等领域。下面列举一些当下最流行的车道线检测方法: 基于图像处理的车道线检测方法。该方法是通过图像处理技术从摄像头传回的图像中提取车道线信息的一种方法,…...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...
FFmpeg 低延迟同屏方案
引言 在实时互动需求激增的当下,无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作,还是游戏直播的画面实时传输,低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架,凭借其灵活的编解码、数据…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命
在华东塑料包装行业面临限塑令深度调整的背景下,江苏艾立泰以一场跨国资源接力的创新实践,重新定义了绿色供应链的边界。 跨国回收网络:废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点,将海外废弃包装箱通过标准…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...

GC1808高性能24位立体声音频ADC芯片解析
1. 芯片概述 GC1808是一款24位立体声音频模数转换器(ADC),支持8kHz~96kHz采样率,集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器,适用于高保真音频采集场景。 2. 核心特性 高精度:24位分辨率,…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)
本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...

视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)
前言: 最近在做行为检测相关的模型,用的是时空图卷积网络(STGCN),但原有kinetic-400数据集数据质量较低,需要进行细粒度的标注,同时粗略搜了下已有开源工具基本都集中于图像分割这块,…...

GitFlow 工作模式(详解)
今天再学项目的过程中遇到使用gitflow模式管理代码,因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存,无论是github还是gittee,都是一种基于git去保存代码的形式,这样保存代码…...