默认成员函数:详解类的隐式操作

news2024/11/14 17:15:45

在这里插入图片描述

目录

  • 一.类的默认成员函数
    • 二.构造函数
      • 三.析构函数。
        • 四.拷贝构造函数
          • 五.赋值运算符重载

一.类的默认成员函数

类的默认成员函数就是定义一个类后,类会自动生成的成员函数,若我们显示定义则类不会自动生成。

二.构造函数

在数据结构学习阶段我们手撕过栈、链表、队列等数据结构,当时我们是用C语言来实现的,每一种数据结构都有自己的初始化和销毁函数。这两个函数对数据结构的使用非常重要,但是我们又常常忘记使用,所以C++在类中设定了默认成员函数——构造函数,它的作用是初始化函数
他有以下的特征:

  1. 函数名与类名相同。
  2. 无返回值(连void都不用写
  3. 函数可以重载
  4. 若无显示定义则在类成员实例化的时候自动调用

还有以下特点要注意,这里我们使用经典的日期类作讲解:

class Date
{
public:
	Date()//无参的构造函数
	{
		_year = 2023;
		_month = 5;
		_day = 1;
	}
	// 全缺省的构造函数
	Date(int year = 1900, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}

private:
	int _year;
	int _month;
	int _day; 
};

如上代码,我们已经显示定义了构造函数——一个无参的,一个全缺省的,显然我们要调用时就会有分歧,所以我们规定,调用无参的函数时连括号都不用写:

int mian()
{
	Date d1;//调用无参的构造函数
	Date d2();//调用全缺省的构造函数
	Date d3(2023,4,5);//调用全缺省的构造函数
	return 0;
}

如果类中未显示定义构造函数,编译器则会生成一个无参的默认构造函数。但是自动生成的默认构造函数只会初始化自定义类型不会初始化内置类型(在不同的编译器上有所区别)。内置类型就是语言提供的数据类型如:int/char等,自定义类型就是我们自己定义的类型如:struct/class/union等。
这样问题就来了,日期类中如果我们忘记定义构造函数,因为日期类成员全是内置类型,则编译器自动生成的构造函数无法完成对类成员的初始化,所以在C++11中规定了,内置类型成员变量在类中声明的时候可以给默认值。还有要注意的:无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为是默认构造函数。
那么我们什么时候需要自己写构造函数,什么时候用编译器生成的呢:

  1. 一般来说,有内置类型并且内置类型未赋符合要求的缺省值时,就需要我们自己编写构造函数
  2. 如果成员全是自定义类型的则可以使用编译器生成的默认成员函数

三.析构函数。

析构函数就是销毁清理函数,完成对象资源的清理工作,他有以下特征:

  1. 析构函数名是类名前面加上~。
  2. 析构函数无返回值 无参数
  3. 析构函数无法重载,一个类只能有一个析构函数,若未显式定义则编译器自动生成。
  4. 对象生命周期结束时,系统自动调用析构函数。

析构函数与构造函数相似:内置类型不会做处理,自定义类型会调用它的析构函数。
由此判断:

  1. 一般情况下,有动态申请资源,就需要显示写析构函数释放资源
  2. 没有动态申请的资源,不需要写析构
  3. 需要释放资源的成员都是自定义类型,不需要写析构

四.拷贝构造函数

当我们想创建两个成员相同的对象时,可以采用用已经存在的对象初始化,这就要使用到拷贝构造函数。他只有一个形参是对本类型对象的引用,拷贝构造函数时构造函数的一个重载,形参如果不使用引用而采用传值调用的话会引发无穷递归调用——因为内置类型的传值调用需要中间变量拷贝来完成而自定义类型传参的值拷贝需要拷贝构造函数完成
若未显式定义,编译器会自动生成一个默认拷贝构造函数:内置类型会完成值拷贝/浅拷贝,而自定义类型会调用他的拷贝构造函数。
注意:类中如果没有涉及资源申请时,拷贝构造函数是否写都可以,一旦涉及到资源申请时,则拷贝构造函数是一定要写的,否则就是浅拷贝

指针无论是什么类型的都是内置类型。

五.赋值运算符重载

运算符重载是具有特殊函数名的函数。
函数名字为:关键字operator后面接需要重载的运算符符号。
函数原型:返回值类型 operator操作符(参数列表)
运算符重载需要注意一下几点:

  1. 重载操作符必须有一个类类型参数
  2. 用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不 能改变其含义
  3. 不能通过连接其他符号来创建新的操作符:比如operator@
  4. 作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏的this
  5. .* sizeof :: ?: . 注意以上5个运算符不能重载。

诸如下面的代码就是运算符重载:

// >运算符重载

	bool operator>(const Date& d)
	{
		return !(*this <= d);
	}




	// ==运算符重载
	bool operator==(const Date& d)
	{
		return _year == d._year
			&& _month == d._month
			&& _day == d._day;
	}



	// >=运算符重载
	bool operator >= (const Date& d)
	{
		return !(*this < d);
	}


	// <运算符重载
	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 !(*this > d);
	}


	// !=运算符重载
	bool operator != (const Date& d)
	{
		return !(*this == d);
	}

赋值运算符重载需要注意:

  1. 参数类型:const T&,传递引用可以提高传参效率
  2. 返回值类型:T&,返回引用可以提高返回的效率,有返回值目的是为了支持连续赋值
  3. 检测是否自己给自己赋值
  4. 返回*this :要复合连续赋值的含义
class Date

{ 

public :
 Date(int year = 1900, int month = 1, int day = 1)
 {
 _year = year;
 _month = month;
 _day = day;
 }
 
 Date (const Date& d)
 {
 _year = d._year;
 _month = d._month;
 _day = d._day;
 }
 
 Date& operator=(const Date& d)
 {
 	if(this != &d)
 	{
 		_year = d._year;
 		_month = d._month;
 		_day = d._day;
 	}
 	return *this;
 }

private:
 int _year ;
 int _month ;
 int _day ;
};

还有几点需要注意的!
赋值重载不能写成全局(默认成员函数都不能写成全局函数)但是可以声明和定义分离(也不一定还要注意访问类成员私有共有问题)
C++规定: ++a 前缀运算符 a.operator() 不需要加参数a++后缀运算符 a.operator(int) 需要加参数。
当一元运算符作为成员函数重载时参数表中没有参数,那个惟一的操作数以this指针的形式隐藏在参数表中;当作为非成员函数重载时,那个惟一的操作数必须出现在参数表中。

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

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

相关文章

VC++ | MFC应用程序设计:框架搭建

VC | MFC应用程序设计&#xff1a;框架搭建 时间&#xff1a;2023-05-01 文章目录 VC | MFC应用程序设计&#xff1a;框架搭建1.启动程序2.新建项目2-1.新建项目2-2.应用程序类型2-3.文档模板属性2-4.用户界面功能2-5.高级功能选项2-6.生成的类2-7.解决方案资源管理器 3.工程文…

如何在外远程控制我的世界服务器 - MCSM面板【端口映射】

文章目录 概述1.MCSManager 安装2.内网穿透2.1 安装cpolar内网穿透 3. 访问公网地址4.固定公网地址4.1 保留一个二级子域名4.2 配置固定二级域名4.3 访问固定公网地址 5. 设置节点公网地址6. 固定节点公网地址6.1 保留一个固定tcp地址6.2 配置固定TCP地址 转载自远程穿透文章&a…

【Latex】有关于Latex tabularray的一些很不错的教程、模板

1. 简介&#xff1a; 除了大家熟知的tabular&#xff0c;Latex在2021年出了一个table排版的新包&#xff1a;tabularray。 笔者这几天初步体验了一下tabularray&#xff0c;个人觉得tabularray明显比tabular的使用体感好不少。 不管是从排版的效果、便捷程度&#xff0c;还是…

基于NumPy构建LSTM模块并进行实例应用(附代码)

文章目录 0. 前言0.1 读本文前的必备知识 1. LSTM架构2. LSTM正向传播代码实现2.1 隐藏层正向传播2.2 输出层正向传播 3. LSTM反向传播代码实现3.1 输出层反向传播3.2 隐藏层反向传播 4. 实例应用说明5. 运行结果6. 后记6 完整代码 0. 前言 按照国际惯例&#xff0c;首先声明&a…

目标跟踪--卡尔曼滤波 与 匈牙利算法

目前主流的目标跟踪算法都是基于Tracking-by-Detecton策略&#xff0c;即基于目标检测的结果来进行目标跟踪。 跟踪结果中&#xff0c;每个bbox左上角的数字是用来标识某个人的唯一ID号。那么问题就来了&#xff0c;视频中不同时刻的同一个人&#xff0c;位置发生了变化&#x…

西瓜书读书笔记整理(三)—— 第二章 模型评估与选择

第二章 模型评估与选择 第 2 章 模型评估与选择2.1 经验误差与过拟合1. 错误率 / 精度 / 误差2. 训练误差 / 经验误差 / 泛化误差3. 过拟合 / 欠拟合4. 学习能力5. 模型选择 2.2 评估方法1. 评估方法概述2. 留出法3. 交叉验证法4. 自助法5. 调参 / 最终模型 2.3 性能度量1. 回归…

【JavaEE】UDP数据报套接字—实现回显服务器(网络编程)

博主简介&#xff1a;想进大厂的打工人博主主页&#xff1a;xyk:所属专栏: JavaEE初阶 本篇文章将带你了解什么是网络编程&#xff1f; 网络编程&#xff0c;指网络上的主机&#xff0c;通过不同的进程&#xff0c;以编程的方式实现网络通信&#xff08;或称为网络数据传输&am…

中断-STM32

中断-STM32 中断:在主程序运行过程中&#xff0c;出现了特定的中断触发条件 (中断源)&#xff0c;使得CPU暂停当前正在运行的程序转而去处理中断程序处理完成后又返回原来被暂停的位置继续运行。 中断优先级:当有多个中断源同时申请中断时&#xff0c;CPU会根据中断源的轻重缓…

Java程序猿搬砖笔记(十一)

文章目录 Hexo博客 Next主题图片防盗链问题Springboot Druid数据库密码加密配置步骤Java统计字符串出现的次数Java获取某个字符在字符串中出现第N次的位置Maven激活指定profileMaven中resources标签的用法详解MySQL 字符集不一致报错EasyExcel日期格式化Configuration、Compone…

gradle Task 详解

Task定义和配置 查看工程下所有的task&#xff0c;使用如下命令 gradle tasks 定义一个task task创建的源码 参数分别是 task 名称&#xff0c;和一个 closure。groovy语法的closure可以写在小括号外面&#xff0c;小括号可以省略 task的源码 public interface Task extends…

【Java笔试强训 25】

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔&#x1f93a;&#x1f93a;&#x1f93a; 目录 一、选择题 二、编程题 &#x1f525;星际密码…

RabbitMQ死信队列延迟交换机

RabbitMQ死信队列&延迟交换机 1.什么是死信 死信&死信队列 死信队列的应用&#xff1a; 基于死信队列在队列消息已满的情况下&#xff0c;消息也不会丢失实现延迟消费的效果。比如&#xff1a;下订单时&#xff0c;有15分钟的付款时间 2. 实现死信队列 2.1 准备E…

网络编程代码实例:IO复用版

文章目录 前言代码仓库内容代码&#xff08;有详细注释&#xff09;server.cclient_select.cclient_poll.cclient_epoll.c 结果总结参考资料作者的话 前言 网络编程代码实例&#xff1a;IO复用版。 代码仓库 yezhening/Environment-and-network-programming-examples: 环境和…

[Linux]网络连接、资源共享

​⭐作者介绍&#xff1a;大二本科网络工程专业在读&#xff0c;持续学习Java&#xff0c;输出优质文章 ⭐作者主页&#xff1a;逐梦苍穹 ⭐所属专栏&#xff1a;Linux基础操作。本文主要是分享一些Linux系统常用操作&#xff0c;内容主要来源是学校作业&#xff0c;分享出来的…

详解c++---vector模拟实现

目录标题 准备工作构造函数迭代器的完善性质相关的函数实现reservepush_back[ ]emptyresizeinserteraseerase后迭代器失效问题swapclear~vector老式拷贝构造迭代器构造新式拷贝构造老式赋值重载新式赋值重载N个数据的构造vector的浅拷贝问题 准备工作 首先我们知道vector是一个…

HTB靶机06-Beep-WP

beep 靶机IP&#xff1a;10.10.10.7 攻击机IP&#xff1a;10.10.14.6 web RCE漏洞利用、nmap提权 扫描 nmap 常规扫描&#xff1a; ┌──(xavier㉿xavier)-[~/HTB/005-Beep] └─$ sudo nmap -sSV -sC 10.10.10.7 -oN nmap1.out Starting Nmap 7.91 ( https://nmap.org …

《道德经》

《道德经》是春秋时期老子&#xff08;李耳&#xff09;的哲学作品&#xff0c;又称《道德真经》、《老子》、《五千言》、《老子五千文》&#xff0c;是中国古代先秦诸子分家前的一部著作&#xff0c;是道家哲学思想的重要来源。 道德经分上下两篇&#xff0c;原文上篇《德经…

网络安全: CIDR无类别路由

网络安全&#xff1a; CIDR无类别路由 CIDR是无类别路由&#xff0c;出现CIDR的原因是因为ipv4的地址被使用完客&#xff0c;CIDR的出现暂缓了ipv4用完的速度。 原本的ipv4很刻板&#xff0c;网络号分成8位&#xff0c;16位&#xff0c;24位作为掩码&#xff0c;也就是 xxx.0…

DRY编码原则

基本情况 DRY&#xff0c;Don’t repeat yourself&#xff0c;就是不要重复你自己的意思。 不要重复&#xff0c;是多么简单的意思了&#xff0c;重复就是多了一个一样的东西&#xff0c;为什么多一个呢&#xff0c;一个就可以了&#xff0c;这样才简单&#xff0c;这是一个常…

【报错】arXiv上传文章出现XXX.sty not found

笔者在overleaf上编译文章一切正常&#xff0c;但上传文章到arxiv时出现类似于如下报错&#xff1a; 一般情况下观察arxiv的编译log&#xff0c;不通过的原因&#xff0c;很多时候都是由于某一行导入了啥package&#xff0c;引起的报错&#xff1b;但是如果没有任何一个具体的…