类的六个默认成员函数

news2024/12/25 12:24:38

1.类的6个默认成员函数

如果一个类中什么成员都没有,简称为空类。空类中什么都没有吗?并不是的,任何一个类在我们不写的情 况下,都会自动生成下面6个默认成员函数。

image-20220416212744174

2.构造函数

构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象时由编译器自动调用,保证每个数据成员都有一个合适的初始值,并且在对象的生命周期内只调用一次。

class Date
{
public:
	Date(int year = 0,int month = 0,int day = 0)//构造函数(全缺省)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d1(2022, 2, 15);
	d1.Print();
	Date d2;
	d2.Print();

	return 0;
}

image-20220416214029326

构造函数的特性:

  1. 函数名与类名相同。
  2. 无返回值。
  3. 对象实例化时编译器自动调用对应的构造函数。
  4. 构造函数可以重载。
  5. 如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦用户显式定义编译器将不再生成。编译器自动生成的默认构造函数不会初始化内置类型(基本类型),如:int , char , double等。但是会初始化我们的自定义类型。如我们用class,struct等定义的类型。
  6. 无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。注意:无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为是默认成员函数。

哪些属于默认构造函数?

  • 我们没写编译器自己生成的
  • 我们写的无参的
  • 我们写的全缺省的

3.析构函数

析构函数:与构造函数功能相反,析构函数不是完成对象的销毁,局部对象销毁工作是由编译器完成的。而 对象在销毁时会自动调用析构函数,完成类的一些资源清理工作。

特性:析构函数是特殊的成员函数。其特征如下:

  1. 析构函数名是在类名前加上字符 ~。
  2. 无参数无返回值。
  3. 一个类有且只有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。
  4. 对象生命周期结束时,C++编译系统系统自动调用析构函数。
  5. 析构函数的调用也符合先进后出

4.拷贝构造函数

拷贝构造函数也是特殊的成员函数,其特征如下:

  1. 拷贝构造函数是构造函数的一个重载形式。
  2. 拷贝构造函数的参数只有一个且必须使用引用传参,使用传值方式会引发无穷递归调用。
  3. 若未显示定义,系统生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按字节序完成拷,贝这种拷贝我们叫做浅拷贝或者值拷贝。

image-20220417203225232

从此以后注意,函数传参,自定义类型的对象,一般推荐引用传参。如果还要继续使用传值传参,也不是不可以,但是每次调用都会调用拷贝构造

5.运算符重载

C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。

函数名字为:关键字operator后面接需要重载的运算符符号。

函数原型:返回值类型 operator操作符(参数列表)

image-20220417205259546

注意:

1.不能通过连接其他符号来创建新的操作符:比如operator@

2.重载操作符必须有一个类类型或者枚举类型的操作数

3.用于内置类型的操作符,其含义不能改变,例如:内置的整型+,不能改变其含义

4.作为类成员的运算符重载函数时,操作符有一个默认的形参this,限定为第一个形参

5…* 、:: 、sizeof 、?: 、. 注意这5个运算符不能重载。

6.&重载和const&重载

这两个默认成员函数一般不用重新定义 ,编译器默认会生成。

image-20221213235438762

7.练习编写默认成员函数

我们以实现一个日期类为例,练习一下

Date.h

#pragma once
#include <iostream>

using std::cin;
using std::cout;
using std::endl;

bool IsLeapYear(const int year);
int GetMonthDay(const int year, const int month);
class Date
{
public:
	Date(int year = 0, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	
	//Date类成员只有三个int,不需要写析构函数和拷贝构造

	Date& operator=(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
		return *this;   //这个函数之所以要有返回值,是为了解决  d3 = d2 = d1 这种情况
	}

	&重载和const&重载  这两个默认成员函数绝大多数情况下不需要自己写
	//Date* operator&()
	//{
	//	return this;
	//}
	//const Date* operator&()const
	//{
	//	return this;
	//}

	//日期的比较函数  这几个函数都比较短,直接定义在类里面了,在类里面定义的函数默认是内联函数
	bool operator>(const Date& d)const
	{
		if (_year > d._year)
			return true;
		if (_year == d._year && _month > d._month)
			return true;
		if (_year == d._year && _month == d._month && _day > d._day)
			return true;
		return false;
	}
	bool operator==(const Date& d)const
	{
		return _year == d._year
			&& _month == d._month
			&& _day == d._day;
	}
	bool operator<(const Date& d)const
	{
		if (*this > d || *this == d)
			return false;
		return true;
	}
	bool operator>=(const Date& d)const
	{
		if (*this < d)
			return false;
		return true;
	}
	bool operator<=(const Date& d)const
	{
		if (*this > d)
			return false;
		return true;
	}
	bool operator!=(const Date& d)const
	{
		if (*this == d)
			return false;
		return true;
	}
	
	
	//日期+-天数
	Date& operator+=(int day);
	Date operator+(int day)const;
	Date& operator-=(int day);
	Date operator-(int day)const;

	//日期前置++--和后置++--
	//为了区分前置和后置,有这样一个约定,在重载后置++--多一个int参数
	//由于前置++返回的是++后的值,可以传引用返回,而后置返回的是++之前的值,需要先创建一个临时变量保存++之前的值,在传值返回
	//前置++--相比于后置少了两次拷贝构造,效率稍微高一些
	Date& operator++();
	Date operator++(int);
	Date& operator--();
	Date operator--(int);

	//两个日期差多少天
	int operator-(const Date& d)const;

	void Print()const //这个const修饰的是this指针,使this指针指向的内容不能被修改的
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

Date.cpp

#define _CRT_SECURE_NO_WARNINGS 1
#include "Date.h"

bool IsLeapYear(const int year)
{
	if (year % 4 == 0 && year % 100 != 0)
		return true;
	if (year % 400 == 0)
		return true;
	return false;
}
int GetMonthDay(const int year, const int month)
{
	const static int arr[] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
	int days = arr[month];
	if (IsLeapYear(year) && month == 2)
		days += 1;
	return days;
}
Date& Date::operator+=(int day)
{
	while (day--)
	{
		_day++;
		if (_day > GetMonthDay(_year, _month))
		{
			_month++;
			_day = 1;
			if (_month > 12)
			{
				_year++;
				_month = 1;
			}
		}
	}
	return *this;
}

Date Date::operator+(int day)const
{
	//我们知道i+12不影响i的值,所以为了不改变原来的Date的值,我们先拷贝构造一个,并且这里不能传引用返回,因为copy是局部变量
	Date copy = *this;
	copy += day;
	return copy;
}

Date& Date::operator-=(int day)
{
	while (day--)
	{
		_day--;
		if (_day == 0)
		{
			_month--;
			if (_month == 0)
			{
				_year--;
				_month = 12;
			}
			_day = GetMonthDay(_year, _month);
		}
	}
	return *this;
}

Date Date::operator-(int day)const
{
	Date copy = *this;
	copy -= day;
	return copy;
}

Date& Date::operator++()
{
	*this += 1;
	return *this;
}

Date Date::operator++(int)
{
	Date copy = *this;
	*this += 1;
	return copy;
}

Date& Date::operator--()
{
	*this -= 1;
	return *this;
}
Date Date::operator--(int)
{
	Date copy = *this;
	*this -= 1;
	return copy;
}

int Date::operator-(const Date& d)const
{
	//让小的日期++,直到和大的日期相等为止
	int count = 0;
	int flag = -1;
	Date min = *this;
	Date max = d;
	if (min > max)
	{
		min = d;
		max = *this;
		flag = 1;
	}
	while (min < max)
	{
		min++;
		count++;
	}
	return flag * count;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

STM32F4 | 跑马灯实验

文章目录一、 STM32F4 IO 口简介二、硬件设计三、软件设计1.位带操作&#xff08;F7除外&#xff09;四、实验现象五、STM32CubeMX 配置 IO 口输入在本章中&#xff0c;我们将通过代码控制 ALIENTEK 阿波罗 STM32 开发板上的两个 LED 灯 DS0 和 DS1 交替闪烁&#xff0c;实…

【salesforce Admin必备】-想到啥写点啥

【salesforce Admin必备】-想到啥写点啥 文章目录【salesforce Admin必备】-想到啥写点啥前言一&#xff0c;货币相关1.带汇率的多种货币-Activate multiple currencies with exchange rates1.1 启用多币种2.Update the Exchange Rate with ACM2.1启用高级货币管理&#xff08;…

数据结构【树和二叉树的相关知识和题目】

文章目录引言&#xff1a;一、树和二叉树的相关知识&#xff08;一、&#xff09;什么是树1.树&#xff08;1.&#xff09;日常生活中的树&#xff08;2.&#xff09;树的基本概念&#xff08;非线性结构&#xff09;&#xff08;3.&#xff09;代码人眼中的树&#xff1a;&…

ORB-SLAM2 --- Tracking::UpdateLocalKeyFrames函数

目录 1.函数作用 2. 函数步骤 3.code 4.函数解析 4.1 记录共视 4.2 更新局部关键帧&#xff08;mvpLocalKeyFrames&#xff09; 4.3 更新当前帧的参考关键帧&#xff0c;与自己共视程度最高的关键帧作为参考关键帧 1.函数作用 跟踪局部地图函数里&#xff0c;更新局部…

【在SpringBoot项目中删除相册数据--Service层】

由于AlbumMapper.java中已经实现了“根据id删除数据表中的相册数据”&#xff0c;所以&#xff0c;可以直接从Service开始开发此功能。 先在IAlbumService中添加抽象方法&#xff1a; /** * 删除相册 * param id 尝试删除的相册的id */ void delete(Long id); 然后&#xf…

[附源码]Python计算机毕业设计SSM基于web的烟草售卖系统(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Android Studio Gradle 无限 Build「假死」

Android Studio Gradle 无限 Build「假死」 解决方案 工程配置 Gradle 的 gradle.properties 文件中添加如下代码&#xff1a; org.gradle.daemontrue org.gradle.paralleltrue然后重新 Sync 工程&#xff0c;漫长等待依赖下载完成后&#xff0c;重新 Build 项目即可 补充 …

【Unity 3D 从入门到实战】Unity 3D 组件总结

目录 一&#xff0c;前言 二&#xff0c;常用组件 1&#xff0c;Transform 组件 2&#xff0c;Mesh Filter 组件 3&#xff0c;Box Collider 组件 4&#xff0c;Rigidbody 组件 5&#xff0c;脚本组件 三&#xff0c;总结 一&#xff0c;前言 组件是 Unity 3D 中的重要…

Attention Is All You Need

摘要 The dominant sequence transduction models 显性序列转换模型。complex recurrent 复杂的递归。convolutional neural networks 卷积神经网络。an encoder and a decoder 编码器和解码器。The best performing models性能最佳的模型the encoder →\rightarrow→ an atte…

D. Lucky Chains

传送门 题意&#xff1a;给你两个数x,y让你求满足xk,yk并且GCD(xk,yk)!1的最小值。 思路&#xff1a;要求满足xk,yk并且GCD(xk,yk)!1的最小值&#xff0c;那么就相等于存在(xk)%d(yk)%d 变化一下就等于(x-y)%d0&#xff0c;那么就是找x-y的约数&#xff0c;然后这个约数可能是…

疫情散去想看电影,用css动画模拟一个阿凡达2完美开场

在历经了艰苦卓绝的3年抗疫后&#xff0c;疫情终于还是来了&#xff0c;很多小伙伴变成了小洋人酸奶&#xff0c;我相信过不了多少天&#xff0c;疫情终将散去&#xff0c;那个时候就可以和家人走进电影院啦。 今天用css布局一个阿凡达2的影院场景&#xff0c;提前过一过瘾。 目…

ARM 异常返回地址

armv7-a armv8-a linux5.15 Preferred exception return address armv7 exception return address correction armv8-32 exception return address correction armv8-64 没有查到link value offset表 arm32 data abort exception为例 周期1周期2周期3周期4周期5指令1pc-8取指…

[附源码]Node.js计算机毕业设计电影推荐系统Express

项目运行 环境配置&#xff1a; Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境&#xff1a;最好是Nodejs最新版&#xff0c;我…

【LSTM预测】基于鲸鱼算法优化双向长短时记忆BiLSTM(多输入单输出)航空发动机寿命预测含Matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …

CloudCompare算法库(CCCorelib)编译与使用

文章目录一、简介二、编译过程三、举个栗子优秀的算法库&#xff0c;值得所有点云爱好者去使用和研究*~*。 一、简介 之前一直没注意到CloudCompare的作者&#xff08;光头大佬&#xff09;已经将CloudCompare的算法库与其可视化部分进行了分离&#xff0c;今天正好有同学问了这…

以太坊地址Address介绍附代码示例

Address是什么 通常情况下&#xff0c;地址代表一外部账户或合约账户&#xff0c;它们都可以在区块链上接收&#xff08;目标地址&#xff09;或发送&#xff08;源地址&#xff09;。 更具体地说&#xff0c;它是根据ECDSA算法&#xff0c;从公钥的Keccak-256哈希值的最后20个…

MapRecuce 词频统计案例

文章目录初探MapReduce一、MapReduce核心思想二、MapReduce编程实例-词频统计思路1、map阶段(映射)2、reduce阶段(归并阶段)三、词频统计编程实现1、准备数据文件2、将文件上传到hdfs指定路径3、在java里创建词频统计映射器类4、创建词频统计驱动类5、运行词频统计驱动类&#…

【机器学习】SVM多分类问题及基于sklearn的Python代码实现

SVM多分类问题及Python代码实现1. 什么是SVM&#xff1f;2. SVM的分类3. SVM决策函数类型4. SVM多分类的Python代码实现参考资料1. 什么是SVM&#xff1f; 对于这个点已经介绍的非常多了&#xff0c;不管是西瓜书还是各种博客&#xff0c;就是需要找到一个超平面&#xff0c;用…

【Redis】Zset和Hash类型

Hash类型 Redis hash 是一个键值对集合。Redis hash是一个string类型的field和value的映射表&#xff0c;hash特别适合用于存储对象。 Hash 类型的底层数据结构是由压缩列表或哈希表实现的&#xff1a; 如果哈希类型元素小于512个&#xff0c;所有值的大小小于64字节。Redis…

一不小心手动实现了k8s的自动化构建

背景 由于公司需要对公司内部的软件需要对外部署&#xff0c;对于前端的部署&#xff0c;需要一套部署的方案。尝试了写了一个适配多模块可配置的部署脚本&#xff0c;本文对实现的过程进行一个记录。 目的 脚本采用的是node&#xff0c;前端同学的首选。脚本的目的就是实现k8s…