C++从入门到起飞之——this指针 全方位剖析!

news2024/9/21 18:56:15

 

                                                                                个人主页:秋风起,再归来~

                                                                                           C++从入门到起飞                         

                                                                       个人格言:悟已往之不谏,知来者犹可追

                                                                                        克心守己,律己则安!

目录

1、this指针

2、C++和C语⾔实现Stack对⽐

C实现Stack代码

C++实现Stack代码

3.完结散花


1、this指针

class Data
{
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;
};

• Date类中有Init与Print两个成员函数,函数体中没有关于不同对象的区分,那当d1调⽤Init和 Print函数时,该函数是如何知道应该访问的是d1对象还是d2对象呢?那么这⾥就要看到C++给了 ⼀个隐含的this指针解决这⾥的问题

• 编译器编译后,类的成员函数默认都会在形参第⼀个位置,增加⼀个当前类类型的指针,叫做this 指针。⽐如Date类的Init的真实原型为, void Init(Date* const this, int year, int month, int day)

• 类的成员函数中访问成员变量,本质都是通过this指针访问的,如Init函数中给_year赋值, this- >_year = year;

class Data
{
public:
	void Init(int year, int month, int day)
	{
		this->_year = year;
		this->_month = month;
		this->_day = day;
	}
	void Print()
	{
		cout << this->_year << "/" << this->_month << "/" << this->_day << endl;
	}

private:
	//这里只是声明,并没有开空间
	int _year;
	int _month;
	int _day;
};

• C++规定不能在实参和形参的位置显⽰的写this指针(编译时编译器会处理),但是可以在函数体内显 ⽰使⽤this指针。

1.下⾯程序编译运⾏结果是()

A、编译报错  B、运⾏崩溃 C、正常运⾏

class A
{
public:
	void Print()
	{
		cout << "A::Print()" << endl;
	}
private:
	int _a;
};

int main()
{
	A* p = nullptr;
	p->Print();
	return 0;
}

 答案是正常运行原因就在于我们对类类型进行操作(p->Print)时并不是对指针本身进行解引用操作,而是通过传参调用Print函数,我们只是传了空指针,并没有对空指针进行任何访问,所以程序不会报错。

2.下⾯程序编译运⾏结果是()

A、编译报错  B、运⾏崩溃  C、正常运⾏ 

class A
{
public:
	void Print()
	{
		cout << "A::Print()" << endl;
		cout << _a << endl;
	}
private:
	int _a;
};

int main()
{
	A* p = nullptr;
	p->Print();
	return 0;
}

我们看到程序并没有正常结束,所以答案是运行崩溃,原因在于函数调用时没有问题,但我们在函数执行期间对空指针进行了解引用(非法访问)

 而对于空指针的访问只有在运行时才会发生,而编译器在编译阶段时不会发现的,所以不是编译错误,而是运行时崩溃。

3.this指针存在内存哪个区域的()

A. 栈  B.堆  C.静态区  D.常量区  E.对象⾥⾯

答案是A!

在C++中,`this` 指针是一个隐含的指向当前对象的指针,它不是由程序员分配的,而是编译器自动创建并插入到每个成员函数的隐式参数列表中的。`this` 指针位于函数调用帧(call stack frame)的局部变量区,通常称为栈空间(Stack),用于存储函数执行时需要的临时数据和指向自身对象的数据。

当函数被调用时,`this` 指针会被初始化为指向调用它的对象实例,这对于访问类的私有成员变量特别有用。记住,`this` 永远不会为空,除非是在静态成员函数或者非成员函数中,这时没有特定的对象关联。

2、C++和C语⾔实现Stack对⽐

⾯向对象三⼤特性:封装、继承、多态,下⾯的对⽐我们可以初步了解⼀下封装。

通过下⾯两份代码对⽐,我们发现C++实现Stack形态上还是发⽣了挺多的变化,底层和逻辑上没啥变 化。 

C实现Stack代码

#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
typedef int STDataType;
typedef struct Stack
{
	STDataType* a;
	int top;
	int capacity;
}ST;
void STInit(ST* ps)
{
	assert(ps);
	ps->a = NULL;
	ps->top = 0;
	ps->capacity = 0;
}
void STDestroy(ST* ps)
{
	assert(ps);
	free(ps->a);
	ps->a = NULL;
	ps->top = ps->capacity = 0;
}
void STPush(ST* ps, STDataType x)
{
	assert(ps);
	// 满了, 扩容
	if (ps->top == ps->capacity)
	{
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		STDataType* tmp = (STDataType*)realloc(ps->a, newcapacity *
			sizeof(STDataType));
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}
		ps->a = tmp;
		ps->capacity = newcapacity;
	}
	ps->a[ps->top] = x;
	ps->top++;
}
bool STEmpty(ST* ps)
{
	assert(ps);
	return ps->top == 0;
}
void STPop(ST* ps)
{
	assert(ps);
	assert(!STEmpty(ps));
	ps->top--;
}
STDataType STTop(ST* ps)
{
	assert(ps);
	assert(!STEmpty(ps));
	return ps->a[ps->top - 1];
}
int STSize(ST* ps)
{
	assert(ps);
	return ps->top;
}
int main()
{
	ST s;
	STInit(&s);
	STPush(&s, 1);
	STPush(&s, 2);
	STPush(&s, 3);
	STPush(&s, 4);
	while (!STEmpty(&s))
	{
		printf("%d\n", STTop(&s));
		STPop(&s);
	}
	STDestroy(&s);
	return 0;
}

C++实现Stack代码

#include<iostream>
using namespace std;
typedef int STDataType;
class Stack
{
public:
	// 成员函数
	void Init(int n = 4)
	{
		_a = (STDataType*)malloc(sizeof(STDataType) * n);
		if (nullptr == _a)
		{
			perror("malloc申请空间失败");
			return;
		}
		_capacity = n;
		_top = 0;
	}
	void Push(STDataType x)
	{
		if (_top == _capacity)
		{
			int newcapacity = _capacity * 2;
			STDataType* tmp = (STDataType*)realloc(_a, newcapacity *
				sizeof(STDataType));
			if (tmp == NULL)
			{
				perror("realloc fail");
				return;
			}
			_a = tmp;
			_capacity = newcapacity;
		}
		_a[_top++] = x;
	}
	void Pop()
	{
		assert(_top > 0);
		--_top;
	}
	bool Empty()
	{
		return _top == 0;
	}
	int Top()
	{
		assert(_top > 0);
		return _a[_top - 1];
	}
	void Destroy()
	{
		free(_a);
		_a = nullptr;
		_top = _capacity = 0;
	}
private:
	// 成员变量
	STDataType* _a;
	size_t _capacity;
	size_t _top;
};
int main()
{
	Stack s;
	s.Init();
	s.Push(1);
	s.Push(2);
	s.Push(3);
	s.Push(4);
	while (!s.Empty())
	{
		printf("%d\n", s.Top());
		s.Pop();
	}
	s.Destroy();
	return 0;
}

• C++中数据和函数都放到了类⾥⾯,通过访问限定符进⾏了限制,不能再随意通过对象直接修改数 据,这是C++封装的⼀种体现,这个是最重要的变化。这⾥的封装的本质是⼀种更严格规范的管 理,避免出现乱访问修改的问题。当然封装不仅仅是这样的,我们后⾯还需要不断的去学习。

• C++中有⼀些相对⽅便的语法,⽐如Init给的缺省参数会⽅便很多,成员函数每次不需要传对象地 址,因为this指针隐含的传递了,⽅便了很多,使⽤类型不再需要typedef⽤类名就很⽅便

• 在我们这个C++⼊⻔阶段实现的Stack看起来变了很多,但是实质上变化不⼤。等着我们后⾯看STL 中的⽤适配器实现的Stack,⼤家再感受C++的魅⼒。

3.完结散花

好了,这期的分享到这里就结束了~

如果这篇博客对你有帮助的话,可以用你们的小手指点一个免费的赞并收藏起来哟~

如果期待博主下期内容的话,可以点点关注,避免找不到我了呢~

我们下期不见不散~~

​​​​

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

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

相关文章

深度挖掘行情接口:股票市场中的关键金融数据API接口解析

在股票市场里&#xff0c;存在若干常见的股票行情数据接口&#xff0c;每一种接口皆具备独特的功能与用途。以下为一些常见的金融数据 API 接口&#xff0c;其涵盖了广泛的金融数据内容&#xff0c;其中就包含股票行情数据&#xff1a; 实时行情接口 实时行情接口&#xff1a…

光耦合器技术的实际应用

光耦合器也称为光隔离器&#xff0c;是现代电子产品中的关键组件&#xff0c;可确保电路不同部分之间的信号完整性和隔离。它们使用光来传输电信号&#xff0c;提供电气隔离和抗噪性。 结构和功能 光耦合器通常由以下部分组成&#xff1a; 1.LED&#xff08;发光二极管&#…

Bone Collector-动态规划题解

Bone Collector Problem - 2602 (hdu.edu.cn)https://acm.hdu.edu.cn/showproblem.php?pid2602 Problem Description Many years ago , in Teddy’s hometown there was a man who was called “Bone Collector”. This man like to collect varies of bones , such as dog’…

Ubuntu18 中JDK的安装

文章目录 一、背景说明二、获取安装包三、安装JDK3.1 上传安装包3.2 复制和解压3.3 环境变量的设置3.4 验证安装 四、问题列表4.1 .bashrc文件在哪里&#xff1f;.bashrc是什么&#xff1f;4.2 为什么使用rz上传安装包时会报&#xff1a; 传输失败&#xff1f; 五、总结 一、背…

SpringBoot项目中将word转换为pdf

需求&#xff0c;用户将用户上传的word文件转换成为pdf格式&#xff0c;然后返回 第一步&#xff1a;引入依赖 <dependency><groupId>aspose</groupId><artifactId>aspose-words</artifactId><version>15.8.0-jdk16</version></…

走进标杆 | 宁波市领导一行至金鸡强磁开展专项调研活动

为深入了解supOS助力宁波打造数实融合标杆城市的实践成果&#xff0c;日前&#xff0c;宁波市领导和专家共赴蓝卓supOS标杆项目——宁波金鸡强磁股份有限公司&#xff08;以下简称“金鸡强磁”&#xff09;调研考察&#xff0c;蓝卓总经理助理杨明明、浙江大区副总经理章来胜等…

力扣3202:找出有效子序列的最大长度||

class Solution { public:int maximumLength(vector<int>& nums, int k) {int res0;for(int m0;m<k;m){//假设子序列两数%k之后的结果为m 相当于枚举vector<int> v(k,0);for(auto num:nums){v[num%k]v[(m-num%kk)%k]1; //知道m之后可以知道需要的子序列当前…

做外贸如何高效跟进转化客户

做外贸业务&#xff0c;基本上每天要做的几个事情&#xff0c;开发客户、跟进转化客户、维护客户等等&#xff0c;经常也有外贸新手朋友问我&#xff0c;遇到什么什么客户要怎么跟进&#xff0c;客户不回复怎么办等等&#xff0c;今天就来跟大家聊聊客户跟进转化这块的一些问题…

通俗易懂讲解电池的主要性能参数(下)

接上期内容&#xff0c;上次主要分享影响电池性能评估的两个主要性能参数&#xff1a;电池容量和电池功率。可以点击这里回顾&#xff1a;一起学习电池的主要性能参数和测试方法 今日接着分享电池性能评估的另外两个主要性能参数&#xff1a;电池的使用寿命和自放电率。 上期…

react 快速入门思维导图

在掌握了react中一下的几个步骤和语法&#xff0c;基本上就可以熟练的使用react了。 1、组件的使用。react创建组件主要是类组件和函数式组件&#xff0c;类组件有生命周期&#xff0c;而函数式组件没有。 2、jsx语法。react主要使用jsx语法&#xff0c;需要使用babel和webpa…

SSM 整合(Spring + MyBatis;Spring + Spring MVC)

1. SSM 整合(Spring MyBatis&#xff1b;Spring Spring MVC) 文章目录 1. SSM 整合(Spring MyBatis&#xff1b;Spring Spring MVC)2. 引入相关依赖3. SSM 整合3.1 创建包结构 4. Spring 整合 MyBatis4.1 编写 jdbc.properties4.2 编写 DataSourceConfig 数据源配置4.3 编…

样式布局学习:盒模型浮动FlexboxGrid Layout定位(Positioning响应式布局(Responsive Layout):

看视频确实更容易理解&#xff0c;但是花费时间有点长了&#xff0c;以下是一些官方文档网址&#xff08;可切换中文&#xff09;&#xff0c;也算是节省时间了&#xff1a; 在前端开发中&#xff0c;布局样式是非常重要的一部分&#xff0c;它决定了页面中元素的位置和排列方…

wps office 2019 Pro Plus 集成序列号Vba安装版教程

前言 wps office 2019专业增强版含无云版是一款非常方便的办公软件&#xff0c;我们在日常的工作中总会碰到需要使用WPS的时候&#xff0c;它能为我们提供更好的文档编写帮助我们更好的去阅读PDF等多种格式的文档&#xff0c;使用起来非常的快捷方便。使用某银行专业增强版制作…

snmp++操作之trap

文章目录 snmp六种操作简述Get&#xff08;获取操作&#xff09;&#xff1a;Get Next&#xff08;获取下一个操作&#xff09;&#xff1a;Get Bulk&#xff08;批量获取操作&#xff09;&#xff1a;Set&#xff08;设置操作&#xff09;&#xff1a;Inform&#xff08;通知操…

数据建模标准-面向对象建模

前情提要 数据模型定义 DAMA数据治理体系中将数据模型定义为一种文档形式&#xff0c;数据模型是用来将数据需求从业务传递到IT,以及在IT内部从分析师、建模师和架构师到数据库设计人员和开发人员的主要媒介&#xff1b; 作用 记录数据需求和建模过程中产生的数据定义&…

任意空间平面点云旋转投影至水平面—罗德里格旋转公式

1、背景介绍 将三维空间中位于任意平面上的点云数据&#xff0c;通过一系列的坐标变换&#xff08;平移旋转&#xff09;&#xff0c;使其投影到XOY平面上&#xff0c;同时保证点云的几何中心与XOY平面的原点重合&#xff0c;同时点云形状保持不变。具体效果如下&#xff0c;具…

51单片机8(LED闪烁)

一、软件设计&#xff1a; 1、本章所要实现的功能是&#xff1a;点亮D1指示灯&#xff0c;即让P2.0管脚输出一个低电平。完成后可再控制D1指示灯闪烁&#xff0c;即间隔一段时间点亮和熄灭D1指示灯。那么如何让LED进行闪烁&#xff0c;那么只需要循环的让这个低指针先亮一会&a…

Docker搭建Harbor

1.什么是Harbor Harbor 是 vMware 公司开源的企业级 Docker 〖egistry 项日&#xff0c;其日标是帮助用户迅速搭建一个企业级的 Docker Registry 服务。Harbor以 Docker 公司开源的 Registry 为基础&#xff0c;提供了图形管理UI 、基于角色的访问控制(Role Based Accesscontr…

地图项目涉及知识点总结

序&#xff1a;最近做了一个在地图上标记点的项目&#xff0c;用户要求是在地图上显示百万量级的标记点&#xff0c;并且地图仍要可用&#xff08;能拖拽&#xff0c;能缩放&#xff09;。调研了不少方法和方案&#xff0c;最终实现了相对流畅的地图系统&#xff0c;加载耗时用…

LLaMA 数据集

LLaMA的训练数据集来源多样&#xff0c;涵盖了多个不同的数据集和预处理步骤。以下是详细的描述&#xff1a; 公开数据来源和预处理 CommonCrawl [67%]&#xff1a; 使用CCNet管道&#xff08;Wenzek等人&#xff0c;2020年&#xff09;对2017年至2020年间的五个CommonCrawl转…