[C++]3.类和对象下(this指针补充)+ 类和对象中构造函数和析构函数。

news2024/10/7 17:31:58

类和对象下(this指针补充)+ 类和对象中构造函数和析构函数

  • 一.this补充:
    • 1.概念总结:
    • 2.两个问题:
  • 二.构造函数和析构函数:
    • 一.类的默认构造:
      • 1.初始化和清理:
      • 2.拷贝复制:
      • 3.取地址重载:
    • 二.构造函数:
      • 1.概念:
      • 2.特征总结:
      • 1.默认构造:
      • 2.默认构造的作用:
        • 2-1:表面
        • 2-2:内涵
    • 二.析构函数:
      • 1.概念:
      • 2.特征总结:
      • 3.意义:

一.this补充:

1.概念总结:

1.this 的作为成员函数的形参的时候满足 类的类型 * const this满足这样一个情况,说明this指针是不可以被修改的。
2.只能在成员函数的内部去使用,
3.this指针本质上是成员函数的一个隐藏的形参,通过外面的实参传给形参。实参其实是对象的地址。对象本身不回去存贮this。
4.this指针是成员函数的第一个隐藏的指针形参,通过ecx寄存器把地址值传过去的不需要程序员进行处理。
5.this指针在成员函数中是可以去使用的。

在这里插入图片描述

2.两个问题:

1.this指针存在哪里?
1-1:存在函数栈帧里面。
1-2:vs 2022: 通过ecx寄存器进行存贮:

2.this指针可以为空吗?
this指针可以为空但是这个this指针作为成员函数的时候不可以去访问类的成员变量,只能访问成员函数中不需要访问成员变量的一些函数是不会出问题的。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二.构造函数和析构函数:

一.类的默认构造:

1.当一个类是空类的时候,会默认生成6个默认构造。

1.初始化和清理:

1-1:构造函数主要完成成员变量的初始化工作:
1-2:析构函数主要完成清理工作:

2.拷贝复制:

2-1:拷贝构造是使用同类对象初始化创建对象:
2-2:赋值重载主要是是把一个对象赋值给另一个对象。

3.取地址重载:

3-1:主要是普通对象和const对象取地址,这两个很少会自己实现:

二.构造函数:

1.概念:

构造函数是一个比较特殊的函数,他会在对象初始化的时候由编译器进行自动调用而且只会在一个对象的生命周期中只会去调用一次。

2.特征总结:

1.构造函数名称和类名称相同:
2.构造函数没有返回值:
3.构造函数在对象初始化的时候由编译器自己调用:

//我们的构造函数在这里进行了显示类型的构造:
在这里插入图片描述

4.构造函数是可以重载的:
4-1:函数的无参的构造函数和全缺省的初始化都是正常定义一个对象:
4-2:对象的初始化,显示的去传参数。
在这里插入图片描述
5.5. 如果类中没有进行显示的定义构造函数,那么C++编译器会默认生成一个无参的默认构造。

1.默认构造:

1.用户没有显示的构造函数,其他操作的什么都没有:生成随机值。

在这里插入图片描述

2.构造函数没有参数也是一种默认构造。

在这里插入图片描述

3.构造函数全部缺省也是一种默认构造:

在这里插入图片描述
4.总结:我们在进行对象初始化的时候不需要进行参数的传递,编译器就回去调用默认构造。

2.默认构造的作用:

在这里插入图片描述

2-1:表面

我们下面实现了一个栈这个类,如果我们使用默认构造调用的了默认构造函数进行初始化:

在这里插入图片描述

#include<iostream>
#include<stdlib.h>
#include<assert.h>

using namespace std;

class Stack
{
public:
	//1.初始化:
	Stack(int capacity_num = 5)
	{
		int* tmp = (int*)malloc(sizeof(int) * capacity_num);
		if (tmp == nullptr)
		{
			perror("malloc file");
			exit(-1);
		}
		arr = tmp;
		sz = 0;
		capacity = 5;
	}
	//2.判断栈空:
	bool Empty()
	{
		assert(arr != nullptr);
		if (sz == 0)
		{
			return true;
		}
		return false;
	}
	//3.压栈:
	void Push(int x)
	{
		assert(arr != nullptr);
		if (sz == capacity)
		{
			int* tmp = (int*)realloc(arr, sizeof(int) * (capacity * 2));
			if (tmp == nullptr)
			{
				perror("realloc file");
				exit(-1);
			}
			arr = tmp;
			capacity *= 2;
		}

		arr[sz++] = x;
	}
	//4.获取栈顶元素:
	int top()
	{
		assert(arr != nullptr);
		if (!Empty())
		{
			return arr[sz];
		}
	}
	//5.删除栈顶元素:
	void del()
	{
		assert(arr != nullptr);
		if (!Empty())
		{
			arr[sz--] = 0;
		}
	}
	//6.打印栈中数据:
	void print()
	{
		assert(arr != nullptr);
		if (!Empty())
		{
			for (int i = 0; i < sz; i++)
			{
				cout << arr[i] << "->";
			}
			cout << endl;
		}
	}
private:
	int* arr;
	int sz;
	int capacity;
};

int main()
{
	Stack s1;
	s1.Push(1);
	s1.Push(2);
	s1.Push(3);
	s1.Push(4);

	s1.print();

	s1.del();
	s1.del();

	s1.print();

	return 0;
}
2-2:内涵

C++把类型分成内置类型(基本类型)和自定义类型。内置类型就是语言提供的数据类型,如:int/char…,自定义类型就是我们使用class/struct/union等自己定义的类型,看看下面的程序,就会发现编译器生成默认的构造函数会对自定类型成员_t调用的它的默认成员函数。

我们下面实现一个自己通过栈实现的队列:
请添加图片描述

2-2:(重要:)根据上面的图片我们知道,内置类型是不会去处理的,自定义类型会去调用他自己默认构造!

2-2:根据这个问题我们C++ 11 支持了变量在声明的时候给一个初始值一般是面对的是内置类型,因为内置类型不会去处理:!

在这里插入图片描述

//2.栈实现队列:

class Myqueue
{
public:
	//1.入队列:
	void my_push(int x)
	{
		push.Push(x);
		sum++;
	}
	//2.出队列:
	void my_pop()
	{
		if (!pop.Empty())
		{
			while (!push.Empty())
			{
				pop.Push(push.top());
				push.del();
			}
		}

		pop.del();
		sum--;
	}
	//3.获取队头元素:
	int get_top()
	{
		if (pop.Empty())
		{
			while (!push.Empty())
			{
				int tmp = push.top();
				pop.Push(tmp);

				push.del();
			}
		}

		return pop.top();
	}
	//4.判断队列是否为空:
	bool Eppty()
	{
		if (sum > 0)
		{
			return false;
		}
		return true;
	}
private:
	Stack push;
	Stack pop;
	//注意C++11  中针对内置类型成员不初始化的缺陷又打了一个补丁:
	//内置类型成员变量在类中声明的时候可以给默认值:
	int sum = 0;
};


int main()
{
	Myqueue Q1;
	return 0;
}

二.析构函数:

1.概念:

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

2.特征总结:

1.函数名和类名相同但是需要在前面加上一个~(按位取反)
2.没有参数没有返回类型:
3. 对象生命周期结束时,C++编译系统系统自动调用析构函数
4. 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构函数不能重载。

3.意义:

栈这样的类的析构才是有意义的:

#include<iostream>
#include<stdlib.h>
#include<assert.h>

using namespace std;

class Stack
{
public:
	//1.初始化:
	Stack(int capacity_num = 5)
	{
		int* tmp = (int*)malloc(sizeof(int) * capacity_num);
		if (tmp == nullptr)
		{
			perror("malloc file");
			exit(-1);
		}
		arr = tmp;
		sz = 0;
		capacity = 5;
	}
	//2.判断栈空:
	bool Empty()
	{
		assert(arr != nullptr);
		if (sz == 0)
		{
			return true;
		}
		return false;
	}
	//3.压栈:
	void Push(int x)
	{
		assert(arr != nullptr);
		if (sz == capacity)
		{
			int* tmp = (int*)realloc(arr, sizeof(int) * (capacity * 2));
			if (tmp == nullptr)
			{
				perror("realloc file");
				exit(-1);
			}
			arr = tmp;
			capacity *= 2;
		}

		arr[sz++] = x;
	}
	//4.获取栈顶元素:
	int top()
	{
		assert(arr != nullptr);
		if (!Empty())
		{
			return arr[sz];
		}
	}
	//5.删除栈顶元素:
	void del()
	{
		assert(arr != nullptr);
		if (!Empty())
		{
			arr[sz--] = 0;
		}
	}
	//6.打印栈中数据:
	void print()
	{
		assert(arr != nullptr);
		if (!Empty())
		{
			for (int i = 0; i < sz; i++)
			{
				cout << arr[i] << "->";
			}
			cout << endl;
		}
	}
	//7.栈中数据的清理:
	~Stack()
	{
		free(arr);
		arr = nullptr;
		sz = 0;
		capacity = 0;
	}
private:
	int* arr;
	int sz;
	int capacity;
};

//2.栈实现队列:

class Myqueue
{
public:
	//1.入队列:
	void my_push(int x)
	{
		push.Push(x);
		sum++;
	}
	//2.出队列:
	void my_pop()
	{
		if (!pop.Empty())
		{
			while (!push.Empty())
			{
				pop.Push(push.top());
				push.del();
			}
		}

		pop.del();
		sum--;
	}
	//3.获取队头元素:
	int get_top()
	{
		if (pop.Empty())
		{
			while (!push.Empty())
			{
				int tmp = push.top();
				pop.Push(tmp);

				push.del();
			}
		}

		return pop.top();
	}
	//4.判断队列是否为空:
	bool Eppty()
	{
		if (sum > 0)
		{
			return false;
		}
		return true;
	}
private:
	Stack push;
	Stack pop;
	//注意C++11  中针对内置类型成员不初始化的缺陷又打了一个补丁:
	//内置类型成员变量在类中声明的时候可以给默认值:
	int sum = 5;
};


int main()
{
	Stack s1;


	return 0;
}

1.通过观察下面的动图我们可以发现,在主函数栈帧结束以后我们的类对象开辟的空间被释放了!
请添加图片描述
2.我们观察一下我们实现队列的默认构造和默认析构:

请添加图片描述

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

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

相关文章

数据结构: AVL树

目录 1.AVL树的概念 2.AVL树的模拟实现 AVL树的结构定义 插入 对平衡因子的讨论 旋转 对旋转情况的讨论 1.单旋 1.1左单旋 1.2右单旋 2.双旋 2.1左右双旋 2.2右左双旋 检查是否是AVL树 1.AVL树的概念 当向二叉搜索树中插入新结点后&#xff0c;如果能保证每个结点…

STM32F4XX之串口

一、标准串口&#xff08;UART&#xff09;介绍 1、通信协议相关概念 1.1同步通信和异步通信 (1)同步通信&#xff1a;两个器件之间共用一个时钟线&#xff0c;要发送的数据在时钟的作用下一位一位发送出去。 &#xff08;2&#xff09;异步通信&#xff1a;指两个器件之间没…

Java基础(第一部):IDEA的下载和安装(步骤图) 项目结构的介绍 项目、模块、类的创建。第一个代码的实现

文章目录 IDEA1.1 IDEA概述1.2 IDEA的下载和安装1.2.1 下载1.2.2 安装 1.3 IDEA中层级结构介绍1.3.1 结构分类1.3.2 结构介绍project&#xff08;项目、工程&#xff09;module&#xff08;模块&#xff09;package&#xff08;包&#xff09;class&#xff08;类&#xff09; …

数据结构与算法-树

树 &#x1f388;1.树和二叉树&#x1f388;2.树&#x1f52d;2.1树的定义&#x1f52d;2.2树的4种表示方法&#x1f52d;2.3树的基本术语&#x1f52d;2.4树的抽象数据类型定义 &#x1f388;3.二叉树&#x1f52d;3.1二叉树的定义&#x1f52d;3.2二叉树的抽象数据类型定义&a…

MySQL 性能分析

MySQL 性能分析 对 mysql 进行性能分析&#xff0c;主要就是提升查询的效率&#xff0c;其中索引占主导地位。对 mysql 进行性能分析主要有如下几种方式&#xff1a; 方式一&#xff1a;查看 sql 执行频次 show global status like ‘Com_______’; // global 表示全局 show s…

力扣每日一题49:字母异位词分组

题目描述&#xff1a; 给你一个字符串数组&#xff0c;请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。 字母异位词 是由重新排列源单词的所有字母得到的一个新单词。 示例 1: 输入: strs ["eat", "tea", "tan", "ate&quo…

国产低功耗MCU芯片:Si24R03

Si24R03集成了基于RISC-V核的低功耗MCU和工作在2.4GHz ISM频段的无线收发器模块&#xff0c;是一款高度集成的低功耗SOC片。 应用领域&#xff1a; 1、物联网 2、智N门锁 3、电机控制 4、消费电子 5、工业控制 其无线收发器模块是专为低功耗无线场合设计&#xff0c;在关…

微信小程序开发的OA会议之会议,投票,个人中心的页面搭建及模板

目录 一.自定义组件 1.1.创建 1.2.定义 1.3.编写 1.4.使用 二.会议 2.1.数据 2.2.显示 2.3. 样式 三.个人中心 3.1.页面 3.2.样式 四.投票 4.1.引用 4.2.数据 4.3.页面 4.4.样式 好啦今天就到这里了&#xff0c;希望能帮到你哦&#xff01;&#xff01;&…

UGUI交互组件Dropdown

一.Dropdown的应用 Dropdown控件官方翻译为下拉选单&#xff0c;游戏中有一定程度的使用&#xff0c;其优势是用户体验优秀&#xff0c;节省界面空间&#xff0c;下图为某游戏的实际应用 二.Dropdown对象的结构 对象说明Label当前选中的选项Arrow向下或向上箭头表示展开方向Te…

Ubuntu服务器配置qq邮箱发送信息

效果&#xff1a; 此处设置的是自己给自己发送&#xff0c;配合linux的cron实现定时触发发送事件的效果 实现过程&#xff1a; 安装邮箱客户端Postfix sudo apt-get install postfix配置Postfix&#xff1a;编辑Postfix的主要配置文件 /etc/postfix/main.cf&#xff0c;并在…

uni-app:js实现数组中的相关处理

一、查询数组中&#xff0c;某一项中的某个数据为指定值的项&#xff08;find() 方法&#xff09; 使用分析 使用数组的 find() 方法来查询 id 为 0 的那一项数据。这个方法会返回满足条件的第一个元素&#xff0c;如果找不到符合条件的元素&#xff0c;则返回 undefined。使用…

跨路由器路由设置

1781的eth0网口地址设置为192.168.3.45并接入192.168.3.0网段里&#xff1b; 1781的eth1网口地址设置为10.0.9.20并接入10.0.0.0网段里&#xff0c;并且连接在网关地址为10.0.9.1的路由上。 192.168.1.140的摄像头接在网关为10.0.9.1的路由器上 现在的需求是1781网关在访问19…

CardView设置任意角为圆角

注意&#xff1a;material:1.1.0以上版本在RadiusCardView节点下一定要添加 android:theme“style/Theme.MaterialComponents”&#xff0c;不然会报错&#xff0c;另外&#xff0c;由于是重写自MaterialCardView&#xff0c;所以一定要导入material包&#xff1a; implementat…

2022年京东双11食品饮料品类数据回顾

2022年双11&#xff0c;根据京东官方发布的数据显示&#xff0c;京东百货中&#xff0c;京东新百货的589个品类10025个品牌成交额同比增长100%。而在食品饮料行业中&#xff0c;也有一些在大促期间成交额同比涨幅超过100%的品牌。 下面&#xff0c;结合鲸参谋平台提供的数据&am…

达梦mysql数据迁移出现datetime兼容问题

迁移工具无法连接mysql 这里需要指定驱动即可 数据迁移datetime数据无法导入 原因是时间中间带有T&#xff0c;达梦不支持这个格式的时间 解决办法也很简单&#xff0c;换最新的达梦驱动。 驱动安装文件里边就有&#xff0c;不用再去下载了。

【lesson13】进程地址空间收尾

文章目录 进程地址空间存在的原因原因一原因二原因三 重新理解什么是挂起&#xff1f; 进程地址空间存在的原因 原因一 凡是非法访问或者映射&#xff0c;OS都会识别到&#xff0c;并终止该进程。 例子&#xff1a; 我们会发现我们定义的字符串常量只有只读权限&#xff0c;…

Hadoop3教程(三十):(生产调优篇)纠删码

文章目录 &#xff08;155&#xff09;纠删码原理纠删码原理纠删码相关命令纠删码策略解释 &#xff08;156&#xff09;纠删码案例实操参考文献 &#xff08;155&#xff09;纠删码原理 纠删码原理 默认情况下&#xff0c;一个文件在HDFS里会保留3个副本&#xff0c;以此提高…

2023年【北京市安全员-A证】考试报名及北京市安全员-A证考试资料

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 北京市安全员-A证考试报名根据新北京市安全员-A证考试大纲要求&#xff0c;安全生产模拟考试一点通将北京市安全员-A证模拟考试试题进行汇编&#xff0c;组成一套北京市安全员-A证全真模拟考试试题&#xff0c;学员可…

【大揭秘】美团面试题:ConcurrentHashMap和Hashtable有什么区别?一文解析!

正文 亲爱的小伙伴们&#xff0c;大家好&#xff01;我是小米&#xff0c;一个热爱技术分享的程序员&#xff0c;今天我为大家带来了一篇有关美团面试题的热门话题&#xff1a;ConcurrentHashMap 和 Hashtable 有什么区别。这个问题在Java面试中常常被拿来考察对多线程编程的理…

基于TCP的RPC服务

TCP服务器上的RPC&#xff0c;通过创建一个服务器进程监听传入的tcp连接&#xff0c;并允许用户 通过此TCP流执行RPC命令 -module(tr_server). -author("chen"). -behaviour(gen_server).%% API -export([start_link/1,start_link/0,get_count/0,stop/0 ]).-export(…