【C++入门】类和对象

目录

类的引入

类的定义

类的访问限定符及封装

访问限定符

封装

类的作用域

类的实例化

this指针

this指针的特性

两个经典问题


类的引入

在C语言的结构体中,只能定义变量。C++在此基础上进行了升级,在C++中,结构体内既可以定义变量,也可以定义函数。类是定义同一类所有对象的变量和方法的蓝图或原型。

类的定义

类的定义格式:

class 类名

{

        / /类体:由成员函数和成员变量组成

        / / ……

}; / /分号不能少

class为定义类的关键字。

类体中的内容称为类的成员:类中的变量称为类的属性或成员变量;类中的函数称为类的方法或成员函数。

如果成员函数在类中声明和定义,那么编译器可能会把它当做内联函数处理。、

类的访问限定符及封装

访问限定符

用类将对象的属性和方法结合在一块,使对象跟完善,通过访问权限选择性的将其接口提供给外部用户使用。

类的三个访问限定符:

访问限定符的说明:

>> public修饰的成员在类外可以直接进行访问。 

>> protected 和 private 修饰的成员在类外不能直接被访问。

>> 访问限定符的作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止。

>> 如果后面没有访问限定符,作用域就到 } 即类结束。

>> class的默认访问权限为private,struct的默认访问权限为public。这是class和struct的一个区别。

封装

面向对象的三大特性:封装、继承、多态。这里只对封装进行介绍。

封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。

类的作用域

类定义了一个新的作用域,类的所有成员都在类的作用域中。在类体外定义类的成员时,需要使用::域作用限定符,指明所定义的成员属于哪个类域。

class A
{
public:
	int Add(int x, int y);
private:
	int _a;
	int _b;
};

int A::Add(int x, int y)
{
	return x + y;
}

int main()
{
	A a;
	cout << a.Add(1, 2) << endl;
	return 0;
}

类的实例化

用类类型创建对象的过程叫做类的实例化。

类是对对象进行描述的,是模型一样的东西,限定了类有哪些成员,定义出一个类并没有分配实际的内存空间来存储它。可以把类理解为一张图纸,并没有真正的建造出房子来。

一个类可以实例化出多个对象,实例化的对象占用实际的物理空间,存储类的成员变量。

this指针

下面用一段代码引入:


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

int main()
{
	Date d1;
	d1.Init(2024, 4, 1);
	d1.Print();

	Date d2;
	d2.Init(2024, 4, 2);
	d2.Print();

	return 0;
}

Date类中的两个成员函数Init和Print,它们的函数体中并没有关于不同对象的区分,所以当d1在调用Init函数的时候,它是怎么知道应该去设置d1对象,而不是设置d2对象呢?

C++中通过引入this指针来解决这个问题。

C++编译器给每个【非静态成员函数】增加了隐藏的指针参数this,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中,所有成员变量的操作都是通过该指针去访问,只不过这些操作对用户来说是透明的,即用户不需要来传递,编译器会自动完成。

this指针的特性

下面将借助这段代码引出指针的特性:

class Date
{
public:
	void Init(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
		this = NULL;//验证this指针的指向是否可以改变
	}

	void Print()
	{
		cout << _year << "年" << _month << "月" << _day << "日" << endl;
	}

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

上面代码中,this = NULL; 这句代码是在验证this指针的指向是否可以改变,编译结果是:

 所以可以得出this指针的第一个特性:

>> this指针的指向不可改变,其类型为 类类型 * const。

>> this指针只能在成员函数内部使用。

>> this指针本质上时成员函数的形参,当对象调用成员函数时,将对象的地址作为实参传给this指针。

>> this指针是成员函数隐含的第一个指针形参,一般由编译器通过ecx寄存器自动传递,不需要用户传递。

两个经典问题

1、this指针存在哪?

2、this指针可以为空吗?

this指针是成员函数隐含的一个形参,所以this指针存储在栈中。可以通过一下代码证明:

class Date
{
public:
	void Init(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}

	void Print()
	{
		Date* const& rthis = this;
		cout << &rthis;//通过this的引用来打印this的地址。
		//cout << _year << "年" << _month << "月" << _day << "日" << endl;
	}

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

int main()
{
	Date  d1;
	d1.Print();

	return 0;
}

打开监视窗口,可以看到:

 this的地址在esp和ebp之间,说明this存储在栈中。

第二个问题,这里暂时不给结论,先看代码:

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

int main()
{
	Date d1;
	d1.Init(2024, 4, 1);

	Date* p = &d1;
	p = nullptr;
	p->Print();//报错

	return 0;
}

this指针为空,并且在Print函数中利用this指针去访问成员变量,所以会报错。

再看另一种情况:


class Date
{
public:
	void Init(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}

	void Print()//在函数体中并没有通过this指着去访问成员变量
	{
		cout << "welcom to C++" << endl;
	}

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

int main()
{
	Date d1;
	d1.Init(2024, 4, 1);

	Date* p = &d1;
	p = nullptr;
	p->Print();//正常运行

	return 0;
}

 所以问题的答案为:

this指针可以为空,但是,当this指着为空时,不可以用它去访问成员变量,否则会报错。


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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Leetcode】top 100 二分查找

35 搜索插入位置 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。请必须使用时间复杂度为 O(log n) 的算法。 基础写法&#xff01;&#xff01;&#xff01;牢记…

SAP 批次号过期了不让过账配置 OMCQ - M7 667 671消息号设置为E

系统默认&#xff0c;批次到期过账时只是警告&#xff0c;仓库希望直接卡死 这种不需要增强&#xff0c;直接配置就好了 OMCQ 找到 M7 667 编号&#xff0c;把W改成E就可以了 改成E之后&#xff0c;这个过账就直接报错了 保险起见&#xff0c;把667和671都设置为E

C++ | Leetcode C++题解之第3题无重复字符的最长子串

题目&#xff1a; 题解&#xff1a; class Solution { public:int lengthOfLongestSubstring(string s) {// 哈希集合&#xff0c;记录每个字符是否出现过unordered_set<char> occ;int n s.size();// 右指针&#xff0c;初始值为 -1&#xff0c;相当于我们在字符串的左…

Linux 磁盘分区、挂载、使用情况

Linux无论有几个分区&#xff0c;分给哪一个目录使用&#xff0c;归根结底都只有一个根目录&#xff0c;独立且唯一的文件结构。 Linux中的每个分区都是用来组成整个文件系统的一部分。 Linux采用了一种“载入”的处理方法&#xff1a;整个文件系统包含了一整套的文件目录&…

神经网络发展历程:DNN、CNN、RNN

系列文章目录 李沐《动手学深度学习》多层感知机 模型概念和代码实现 李沐《动手学深度学习》卷积神经网络 相关基础概念 李沐《动手学深度学习》卷积神经网络 经典网络模型 李沐《动手学深度学习》循环神经网络 相关基础概念 李沐《动手学深度学习》循环神经网络 经典网络模型…

深入探究Shiro反序列化漏洞

Shiro反序列化漏洞 什么是shiro反序列化漏洞环境搭建漏洞判断rememberMe解密流程代码分析第一层解密第二层解密2.1层解密2.2层解密 exp 什么是shiro反序列化漏洞 Shiro是Apache的一个强大且易用的Java安全框架,用于执行身份验证、授权、密码和会话管理。使用 Shiro 易于理解的…

docker-compse安装es(包括IK分词器扩展)、kibana、libreoffice

Kibana是一个开源的分析与可视化平台&#xff0c;设计出来用于和Elasticsearch一起使用的。你可以用kibana搜索、查看存放在Elasticsearch中的数据。 Kibana与Elasticsearch的交互方式是各种不同的图表、表格、地图等&#xff0c;直观的展示数据&#xff0c;从而达到高级的数据…

Redis的配置与优化

一、关系型数据库和非关系型数据库 1.1 关系型数据库 一个结构化的数据库创建在关系模型基础上&#xff0c;一般面向于记录&#xff0c;包括&#xff1a;Oracle、MySQL、SQLServer、Microsoft Access、DB2等 1.2 非关系型数据库 除了主流的关系型数据库外的数据库&#xff0c;都…

JimuReport积木报表 v1.7.4 正式版本发布,免费的JAVA报表工具

项目介绍 一款免费的数据可视化报表&#xff0c;含报表和大屏设计&#xff0c;像搭建积木一样在线设计报表&#xff01;功能涵盖&#xff0c;数据报表、打印设计、图表报表、大屏设计等&#xff01; Web 版报表设计器&#xff0c;类似于excel操作风格&#xff0c;通过拖拽完成报…

python高校学生兼职雇佣信息网站vue+django

而随着经济的发展&#xff0c;企业的人力成本也越来越高&#xff0c;而有些工作却存在工作时间不稳定&#xff0c;工作量不确定的特点&#xff0c;不少企业便经常雇佣兼职人员来完成其某些工作而对于另外一-些商家来&#xff0c;有不少产品需要推向校园&#xff0c;因此校园传 …

SSM框架学习——SqlSession以及Spring与MyBatis整合

SqlSession以及Spring与MyBatis整合 准备所需要的JAR包 要实现MyBatis与Spring的整合&#xff0c;很明显需要这两个框架的JAR包&#xff0c;但是只是使用这两个框架中所提供的JAR包是不够的&#xff0c;还需要配合其他包使用&#xff1a; Spring的JAR包MyBatis的JAR包Spring…

CV论文--2024.4.2

1、Unsolvable Problem Detection: Evaluating Trustworthiness of Vision Language Models 中文标题&#xff1a;无法解决的问题检测&#xff1a;评估视觉语言模型的可信度 简介&#xff1a;本文提出了一个新颖且重要的挑战&#xff0c;即视觉语言模型&#xff08;VLM&#x…

[yolox]ubuntu上部署yolox的ncnn模型

首先转换pytorch->onnx->param模型&#xff0c;这个过程可以查资料步骤有点多&#xff0c;参考blog.51cto.com/u_15660370/6408303&#xff0c;这里重点讲解转换后部署。 测试环境&#xff1a; ubuntu18.04 opencv3.4.4(编译过程省略&#xff0c;参考我其他博客) 安装…

BM25 二叉树的后序遍历(postOrder()返回值用void)

import java.util.*;/** public class TreeNode {* int val 0;* TreeNode left null;* TreeNode right null;* public TreeNode(int val) {* this.val val;* }* }*/public class Solution {/*** 代码中的类名、方法名、参数名已经指定&#xff0c;请勿修改&a…

京东云明修“价格战”,暗渡“政企云”

文&#xff5c;白 鸽 编&#xff5c;王一粟 云计算行业越来越“卷”&#xff0c;一边卷大模型&#xff0c;一边卷价格。 2024 刚一开年&#xff0c;阿里云就宣布百余款产品大降价&#xff0c;最高降幅达55%。在阿里云宣布降价后&#xff0c;京东云紧随其后宣布&#xff0…

如何用Git来查看提交记录

2024年4月2日&#xff0c;周二上午 使用 git log 命令查看提交记录。这会列出所有的提交历史&#xff0c;按照时间顺序从最新的提交到最旧的提交显示。默认情况下&#xff0c;git log 会以一种格式化的方式显示提交信息&#xff0c;包括提交哈希值、作者、提交日期和提交信息等…

https安全性 带给im 消息加密的启发

大家好&#xff0c;我是蓝胖子&#xff0c;在之前# MYSQL 是如何保证binlog 和redo log同时提交的&#xff1f;这篇文章里&#xff0c;我们可以从mysql的设计中学会如何让两个服务的调用逻辑达到最终一致性&#xff0c;这也是分布式事务实现方式之一。今天来看看我们能够从http…

深入解析大数据体系中的ETL工作原理及常见组件

** 引言 关联阅读博客文章&#xff1a;探讨在大数据体系中API的通信机制与工作原理 关联阅读博客文章&#xff1a;深入理解HDFS工作原理&#xff1a;大数据存储和容错性机制解析 ** 在当今数字化时代&#xff0c;大数据处理已经成为了企业成功的重要组成部分。而在大数据处…

(C)1007 素数对猜想

1007 素数对猜想 问题描述 输入样例&#xff1a; 20 输出样例&#xff1a; 4 解决方案&#xff1a; #include<stdio.h> #include<string.h> #include<math.h> int main(){int n,d;int a[100000];int flag,jishu0;scanf("%d",&n);memset(a,-1,…

将 Three 带到 Vue 生态系统,TresJs 中文文档上线

将 Three 带到 Vue 生态系统&#xff0c;TresJs 中文文档上线 中文文档上线入门指南 ThreeJS 在创建 WebGL 3D 网站方面是一个奇妙的库&#xff0c;同时他也是一个保持不断更新的库&#xff0c;一些对其封装的维护者&#xff0c;如 TroisJS&#xff0c;往往很难跟上其所有的更…