C++类与对象(二)——构造函数与析构函数

news2024/9/26 20:21:53

文章目录

  • 一.类的默认6个成员函数
  • 二.构造函数
    • 1.引例
    • 2.构造函数的概念及特性
  • 三.析构函数
    • 😋析构函数的特性

前言:

上篇文章初步认识了类以及类的相关知识,本篇将继续深入学习类与对象——类的默认6个成员函数:

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

上一章我们说到,如果一个类中什么成员都没有,那么这个类就叫空类。这么说其实不是很严谨,因为当我们定义好一个,不做任何处理时,编译器会自动生成以下6个默认成员函数

  • 默认成员函数:如果用户没有手动实现,则编译器会自动生成的成员函数:
    在这里插入图片描述
  • 构造函数:主要完成初始化工作
  • 析构函数:主要完成清理工作
  • 拷贝构造:使用已经存在的一个对象初始化创建另一个对象
  • 复制重载:把一个对象赋值给另一个对象
  • 取地址重载普通对象取地址操作
  • 取地址重载const):const对象取地址操作

二.构造函数

1.引例

在C语言阶段,我们在使用的数据结构的时候,每当创建一个Stack对象,首先得调用它的初始化函数StackInit来初始化对象。

typedef int STDataType;
typedef struct Stack
{
	STDataType* a;
	int top;
	int capacity;
}St;

void StackInit(St* ps);
//……
int main()
{
	St s;
	StackInit(&s);

	return 0;
}

在每次使用前,都要先初始化,这样显得太麻烦而且容易遗忘。在C++中,构造函数为我们很好的解决了这一问题。

2.构造函数的概念及特性

构造函数是一个特殊的成员函数。构造函数虽然叫构造,但是其主要作用并不是开辟空间创建对象,而是初始化对象

构造函数具有以下特性

1. 函数名与类名相同
2. 无返回值
3. 对象实例化时,编译器自动调用对应的构造函数
4. 构造函数可以重载

举例:

class Data
{
public:
	// 无参的构造函数
	Data()
	{}
	// 带参的构造函数
	Data(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
private:
	int _year;
	int _month;
	int _day;
};

void TestData()
{
	// 调用无参构造函数
	Data d1;
	// 调用带参的构造函数
	Data d2(2023, 5, 3);
}

注意:

创建对象时编译器会自动调用构造函数,若是调用无参的构造函数,则无需在对象后加(),否则会产生歧义:编译器无法确定是在声明函数还是在创建对象

错误示例:

// 错误示例
Data d3();

5. 如果类中没有显示定义的构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦用户显示定义编译器将不再生成

class Data
{
public:
	// 若用户没有显示定义,则编译器自动生成

	//Data(int year, int month, int day)
	//{
	//	_year = year;
	//	_month = month;
	//	_day = day;
	//}
private:
	int _year;
	int _month;
	int _day;
};

6. 默认生成构造函数,对内置成员不作处理,对自定义类型成员,会调用它的默认构造函数

C++把类型分为内置类型(基本类型)和自定义类型。内置类型就是语言提供的基本数据类型,如:intchardouble……,自定义类型就是我们使用的classstructunion等自己定义的类型

举例:
默认构造函数对内置类型:

class Data
{
public:
	void print()
	{
		cout << _year << '-' << _month << "-" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
void TestData1()
{
	Data d1;
	d1.print();
}

int main()
{
	TestData1();
	return 0;
}

运行结果:

在这里插入图片描述

如图所示,默认构造函数未对内置类型做处理。

默认构造函数对自定义类型:

class stack
{
public:
	// stack的默认构造函数
	stack()
	{
		cout << "stack" << endl;
		_a = nullptr;
		_top = _capacity = 0;
	}
private:
	int* _a;
	int _top;
	int _capacity;
};

class queue
{
public:
	// 不对queue的构造函数做显示定义,测试构造函数
private:
	stack _s;
};

void TestQueue()
{
	queue q;
}
int main()
{
	TestQueue();
	return 0;
}

运行结果:

在这里插入图片描述

如图所示,在创建queue对象时,默认构造函数对自定义成员_s做了处理,调用了它的默认构造函数stack()

  • 但是这种容易混淆的使用方式让很多人感到不满,为什么要针对内置类型和自定义类型做不同的处理呢?终于,在C++11中针对内置类型成员变量不初始化的缺陷,又打了补丁,即:

7. 内置类型成员变量在类中声明时可以给默认值
示例:

class Date
{
public:
	void print()
	{
		cout << _year << '-' << _month << '-' << _day << endl;
	}
private:
	int _year = 0;
	int _month = 0;
	int _day = 0;
};

void TestDate2()
{
	Date d2;
	d2.print();
}

int main()
{
	TestDate2();
	return 0;
}

运行结果:

在这里插入图片描述

默认值:若不对成员变量作处理,则使用默认值

8. 无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只有一个
示例:

class Date
{
public:
	// 1.无参的默认构造函数
	// Date()
	// {
		// ……
	// }
	
	// 2.全缺省的默认构造函数
	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 = 0;
	int _month = 0;
	int _day = 0;
};

三.析构函数

析构函数构造函数的特性相似,但功能恰好相反。构造函数是用来初始化对象的,析构函数是用来销毁对象的。

需要注意的是,析构函数并不是对对象本身进行销毁(因为局部对象出了作用域会自行销毁,由编译器来完成),而是在对象销毁时会自动调用析构函数,对对象内部的资源做清理(如对象stack中的int *a)。

同样,有了析构函数,我们就不用担心创建对象后由于忘记释放内存而造成内存泄漏了。
示例:

class Stack
{
public:
	// 构造函数
	Stack()
	{

	}
	void push(int x);
	bool empty();
	int Top();
	// 手动释放
	void Destory();
private:
	// 成员变量
	int* _a;
	int _top;
	int _capacity;
};

void TestStack()
{
	Stack s;
	s.push(1);
	s.push(2);
	// 手动释放
	s.Destory();
}

😋析构函数的特性

  1. 析构函数名是在类名前加~
  2. 无参数
  3. 无返回值
  4. 一个类只能有一个析构函数。若未显示定义,系统会自动生成默认的析构函数
  5. 析构函数不能重载

示例:

class Date
{
public:
	// 构造函数
	Date()
	{
		cout << "Date()" << endl;
	}
	// 析构函数
	~Date()
	{
		cout << "~Date()" << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

void TestDate3()
{
	// d3生命周期结束时自动调用构造函数
	Date d3;
}

int main()
{
	TestDate3();
}

运行结果:
在这里插入图片描述

6.编译器生成的默认析构函数,对自定义类型调用它的析构函数
示例:

class Stack
{
public:
	// 构造函数
	Stack()
	{
		cout << "stack()" << endl;
		_a = nullptr;
		_top = _capacity = 0;
	}
	// 析构函数
	~Stack()
	{
		cout << "~Stack()" << endl;
		free(_a);
		_a = nullptr;
		_top = _capacity = 0;
	}
private:
	int* _a;
	int _top;
	int _capacity;
};

class queue
{
public:
	// 不对queue的构造函数和析构函数做显示定义
	// 测试默认构造函数和默认析构函数
private:
	Stack _s;
};

void TestQueue1()
{
	queue q;
}

int main()
{
	TestQueue1();
	return 0;
}

运行结果:

在这里插入图片描述

  • 这里与构造函数的区别是:编译器默认生成的析构函数不像构造函数那样区分内置类型与自定义类型

这是因为:内置类型在生命周期结束时会自动销毁。而自定义类类型里可能有动态开辟的空间,因此要进行清理工作。

因此:

7.如果类中没有申请资源时,析构函数可以不写,直接用编译器生成的默认析构函数,比如Date类;有资源申请时,一定要写,否则会造成资源泄露,比如Stack


本文到此结束,码文不易,还请多多支持哦!!

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

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

相关文章

制造企业如何跨越大规模定制鸿沟?中国最大减速机企业的答案来了

导读&#xff1a;传统制造企业如何深度用云&#xff1f; 在中国制造向中国智造的转型中&#xff0c;长三角地区一直扮演着急先锋的角色。总部位于常州的江苏国茂减速机股份有限公司(简称国茂股份)&#xff0c;就是中国制造上云转型的典型代表。 国茂股份成立于1993年&#xff0…

Microelectronic学习章节总结(2)-- data path和control unit设计

文章目录 part1. Data path设计1.1 logic unit1.2 shifter1.3 adder1.4 comparator1.5 multiplier1.6 divider1.7 register file part2. Control unit设计part3. CPU SoC上的其它部件 (TODO&#xff1a;理解总结)3.1 总线AMBA&#xff08;parallel&#xff09; 3.2 Memorymemor…

[C++基础]-类和对象(下)

前言 作者&#xff1a;小蜗牛向前冲 名言&#xff1a;我可以接受失败&#xff0c;但我不能接受放弃 如果觉的博主的文章还不错的话&#xff0c;还请点赞&#xff0c;收藏&#xff0c;关注&#x1f440;支持博主。如果发现有问题的地方欢迎❀大家在评论区指正。 目录 一、深入学…

推荐算法实战项目:AFM 原理以及案例实战(附完整 Python 代码)

本文要介绍的是由浙江大学联合新加坡国立大学提出的AFM模型。通过名字也可以看出&#xff0c;此模型又是基于FM模型的改进&#xff0c;其中A代表”Attention“&#xff0c;即AFM模型实际上是在FM模型中引入了注意力机制改进得来的。 之所以要在FM模型中引入注意力机制&#xf…

PC3-管理员操作

token无效可能&#xff0c;就是token过期了需要配置&#xff1a;&#xff1a;&#xff1a; history 安装可以跳路由在ts文件中&#xff1a;因为在ts文件中还需要store&#xff0c;清空token // 安装可以跳路由在ts文件中npm i history 防止接口出现 token 无效&#xff0c;登…

【C++】AVL平衡二叉树源码剖析

目录 概述 算法 左单旋 右单旋 左右双旋 右左双旋 源码 AVLTree.h test.cpp 概述 AVL树也叫平衡二叉搜索树&#xff0c;是二叉搜索树的进化版&#xff0c;设计是原理是弥补二叉搜索树的缺陷&#xff1a;当插入的数据接近于有序数列时&#xff0c;二叉搜索树的性能严重…

20天能拿下PMP吗?

新版大纲&#xff0c;专注于人员、过程、业务环境三个领域&#xff0c;内容贯穿价值交付范围&#xff08;包括预测、敏捷和混合的方法&#xff09;。除了考试时间由240分钟变更为230分钟、200道单选题变为180道&#xff08;包含单选和多选&#xff09;之外&#xff0c;新考纲还…

【Ubuntu18配置Anaconda深度学习环境】

参考&#xff1a;Ubuntu18配置与ROS 兼容的深度学习环境&#xff08;Anaconda3PyTorch1.10python3.8cuda10.2&#xff09; 1. 前言 之前在Window下安装了Anaconda&#xff0c;熟悉了一下安装过程&#xff0c;Ubuntu18.04下最难的应该就是和ROS Melodic的兼容问题。ROS1是基于P…

Linux常用命令——inotifywait命令

在线Linux命令查询工具 inotifywait 异步文件系统监控机制 补充说明 Inotify一种强大的、细粒度的、异步文件系统监控机制&#xff0c;它满足各种各样的文件监控需要&#xff0c;可以监控文件系统的访问属性、读写属性、权限属性、删除创建、移动等操作&#xff0c;也就是可…

数据结构之第十一章、排序算法

一、排序的概念及引用 1.1排序的概念 排序&#xff1a;所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操作。 1.1.1排序的稳定性 稳定性&#xff1a;假定在待排序的记录序列中&#xff0c;存在多个具…

数据结构之第九章、优先级队列(堆)

目录 一、优先级队列 1.1概念 二、优先级队列的模拟实现 2.1堆的概念 2.2堆的存储方式 2.3堆的创建 2.3.1堆向下调整 2.3.2堆的创建 2.3.3建堆的时间复杂度 2.4堆的插入与删除 2.4.1堆的插入 2.4.2堆的删除 2.5用堆模拟实现优先级队列 三、常用接口介绍 3.1Priori…

计算机组成原理与体系结构

目录 第一章、计算机组成原理与体系结构1、数据的表示1.1.进制转换1.2.原码、反码、补码、移码1.3.数据的表述 2、计算机结构3、Flynn分类法4、CISC与RISC5、流水线技术5.1、流水线的基本概念5.2、流水线的计算5.3、流水线吞吐率计算5.4、流水线加速比计算5.5、流水线的效率 6、…

Python小姿势 - Python的多线程编程

Python的多线程编程 Python的多线程编程提供了一个非常简单的方法来让一个Python程序同时运行多个任务。这个方法通过创建新的线程来实现&#xff0c;线程可以被视为一个单独的执行流程。 为了创建一个新线程&#xff0c;我们需要使用Python的_thread模块中的start_new_thread(…

【IDEA】简单入门:请求数据库表数据

目录 修改编辑与控制台字体大小 二、sprintboot项目入门 【1】直接开始配置Controller 【2】直接请求数据库中的数据&#xff0c;返回json格式 &#xff08;0&#xff09;整合PostgreSQL框架 &#xff08;2&#xff09;实体entity类 &#xff08;3&#xff09;控制类Mai…

快速了解车联网V2X通信

自动驾驶拥有极其巨大的潜力&#xff0c;有可能改变我们的出行方式。它不仅有望永远改变车辆的设计和制造&#xff0c;还会永远改变汽车的所有权乃至整个交通运输业务。要实现全自动驾驶的目标&#xff0c;开发人员需要开发极为复杂的软件&#xff0c;软件中融入的人工智能(AI)…

机械硬盘和固态硬盘有什么区别?如何使用?

案例&#xff1a;怎么区分机械硬盘和固态硬盘&#xff1f; 【我知道硬盘可以用来储存数据&#xff0c;但我不知道机械硬盘和固态硬盘的区别&#xff0c;有没有小伙伴可以详细解释一下。】 硬盘可以用来储存数据&#xff0c;常见的硬盘有两种&#xff0c;分别是机器硬盘和固态…

C++11多线程编程——线程池的实现

学一门新技术&#xff0c;还是要问那个问题&#xff0c;为什么我们需要这个技术&#xff0c;这个技术能解决什么痛点。 一、为何需要线程池 那么为什么我们需要线程池技术呢&#xff1f;多线程编程用的好好的&#xff0c;干嘛还要引入线程池这个东西呢&#xff1f;引入一个新的…

发展文旅夜游项目有哪些好处

夜晚的城市&#xff0c;总是充满着无限的魅力和活力&#xff0c;而文旅夜游更是让这份魅力和活力得到了更好的展现和发挥。新起典文旅科技认为文旅夜游不仅仅是一种旅游方式&#xff0c;更是可以增加城市夜间经济、丰富文化娱乐生活、缓解白天拥堵、提高旅游体验、促进文化交流…

HTTP的特点

灵活可扩展 HTTP 协议最初诞生的时候就比较简单&#xff0c;本着开放的精神只规定了报文的基本格式&#xff0c;比如用空格分隔单词&#xff0c;用换行分隔字段&#xff0c;“headerbody”等&#xff0c;报文里的各个组成部分都没有做严格的语法语义限制&#xff0c;可以由开发…

大厂面试NLP工程师,会考察你哪些方面的能力?

你好&#xff0c;我是周磊。 相信你已经知道&#xff0c;一名AI算法工程师&#xff0c;不但需要基础能力扎实&#xff0c;更要具备良好的工程落地能力。那在NLP工程师面试的时候&#xff0c;你知道面试官会从哪些维度去考察你这两方面的能力吗&#xff1f; 今天我就结合我的一…