C++入门全集(2):类与对象【上】

news2025/1/14 18:20:56

目录

一、前言

二、struct在C++中的变化

三、类的定义

四、类的访问限定符

五、封装

六、类的实例化

七、类对象模型

7.1 如何计算类对象的大小

7.2 类对象的存储方式

八、this指针

8.1 this指针的用途

8.2 this指针的特性

一、前言

C语言是一种面向过程的语言,关注于求解问题的过程,通过函数调用逐步解决问题。

C++在C语言的基础上增加了面向对象编程,将一件事情拆分成不同的对象,关注对象之间的交互

C++认为万事万物皆为对象,都有其自己的属性行为,例如:

人可以作为对象,属性有姓名、年龄、身高......行为有走、跑、跳、说话......

车也可以作为对象,属性有轮胎、方向盘、车灯......行为有载人、放音乐......

具有相同性质的对象,可以抽象为类,不同的人可以属于人类,车属于车类

类是C++的核心特性,通常被称为用户定义的类型,是一种封装了数据和函数的组合。

类中的数据称为成员变量, 函数称为成员函数。

 


二、struct在C++中的变化

在C语言中,在struct定义的结构体中只能定义变量。而在C++中结构体中不仅可以定义变量,还可以定义函数。

因为C++中struct也可以用来定义类。

例如我们要实现一个栈,用C语言实现的话各种接口函数只能在结构体外定义,而用C++实现我们会发现struct中也可以定义函数,例如:

struct Stack
{
	void Init(int capacity = 4)
	{
		_array = (int*)malloc(sizeof(int) * capacity);
		if (nullptr == _array)
		{
			perror("malloc fail");
			return;
		}
		_capacity = capacity;
		_size = 0;
	}

	void Push(int x)
	{
		//...
		_array[_size] = x;
		++_size;
	}

    //...    

	int* _array;
	int _capacity;
	int _size;
};

int main()
{
	Stack s;
	s.Init();
	s.Push(1);
	s.Push(2);
	s.Push(3);
	return 0;
}

另外,在C语言中,结构体的类型名是包含struct的,但是在C++中类型名不包含struct,例如:

 


三、类的定义

虽然C++中可以用struct定义类,但是我们通常喜欢用class来代替它

class ClassName
{
	// 类体:由成员函数和成员变量组成
};

class是定义类的关键字,ClassName是类名,大括号中为类的主体,注意类后的分号不能省略。

类体中的内容为类的成员,其中的变量称为类的属性成员变量,函数称为类的方法成员函数

类有两种定义方式:

(1)成员函数的声明和定义全部放在类体中,如上面栈的定义

(2)成员函数的声明和定义分离,在头文件中定义类,函数的声明放在类体中,在源文件中定义接口函数,如:

需要注意的是,当我们定义了一个类的时候,就是创建了一个类作用域。使用第二种方法定义类时要在成员函数名的前面加上类名和作用域限定符。

另外,成员变量在命名时,建议在前面加上一个下横线_,这样可以方便与形参进行区分

例如:

class Date
{
	void Init(int year)
	{
		// 这里的year到底是成员变量,还是函数形参?
		year = year;
	}

	int year;
};

如果前面加上下横线区分,就能避免这种尴尬的情况。当然你也可以选择其他方式进行区分

不过,在上面第二种类的定义方式中,我们去使用函数的时候会出现以下情况:

这里与C++的访问限定符有关


四、类的访问限定符

C++中有三种访问限定符:public(公有)、protected(保护)和private(私有)

其中,因为C++要兼容C语言,所以struct中的成员默认公有,而class中的成员默认私有,所以才会导致上面那种情况

关于访问限定符的说明:

  • public的成员在类外可以直接被访问,protected和private修饰的成员则不能
  • 访问限定符的作用域从该限定符的位置开始直到下一个限定符出现结束,如果后面没有访问限定符,就遇到大括号结束

当我们将成员函数用public修饰后,就能在类外访问它们了


五、封装

C++面向对象的三大特性:封装、继承、多态

在学习类和对象的阶段,我们主要了解类的封装特性

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

例如一台电脑,提供给用户进行交互的只有各种按钮和插口,而实际工作的是内部的各种硬件。对于用户而言,不需要知道内部的结构如何,只需要知道怎么去使用即可。

在C++中,使用类将数据和方法结合,通过调整访问权限来隐藏对象的内部细节,开放成员函数的权限以供使用,就是一种封装。


六、类的实例化

用类创建对象的过程,称为类的实例化。

类就像一张图纸,限定了类有哪些成员,但是并没有分配实际的内存空间来存储它。我们按照图纸建房子,也就是实例化出具体的对象。

之前我们定义的Stack类是没有空间的,只有Stack类实例化出的对象才占有具体的内存空间

 


七、类对象模型

7.1 如何计算类对象的大小

请问,Stack类实例化出的对象应该是多大呢?

答案是12,据此我们可以推算出,类的大小也是遵守内存对齐规则的,并且只计算成员变量,不计算成员函数

7.2 类对象的存储方式

为什么计算类对象的大小时不包含成员函数呢?

同一类的每个对象中成员变量的值是不一样的,所以需要独立存储。

但是每个对象调用的成员函数是一样的,如果把成员函数存储在对象中,占用对象的内存空间,就导致用一个类实例化多个对象时,每个对象都会保存一份代码,浪费内存空间。

所以我们将成员函数存放在公共的代码段中

问题又来了,下面这两个类的大小是多少呢?

class c1
{
public:
	void func()
	{
		;
	}
};

class c2
{

};

答案是 1  

虽然一个类中只有成员函数,一个类中什么也没有,但是还是会分配1byte的内存空间用来占位,标识对象已被实例化出来了。

这1byte空间不会存储有效数据。


八、this指针

现在我们知道,在C++中成员变量和成员函数是分开存储的,那么当我们调用成员函数的时候,函数是怎么区分是哪个对象调用自己的呢?

C++中提供this指针来解决该问题,this指针指向调用函数的对象,并隐式传递给函数。

我们不能手动显式地在参数列表中添加this指针,编译器自己会完成

8.1 this指针的用途

(1)当形参与成员变量同名时,可用this指针区分

(2)在类的非静态成员函数中返回对象本身

8.2 this指针的特性

(1)this指针本质是一个指针常量:const Type* const pointer,所以在成员函数中不能给this指针赋值

(2)this指针只能在非静态成员函数中使用,在全局函数、静态成员函数中都不能用

(3)this指针本质上是成员函数的形参,当对象调用成员函数时,编译器将对象地址作为实参传递给this形参,所以this指针不存储在对象中

(4)this指针会因编译器不同而存储在不同的位置,通常存在栈中,vs上存储在ecx寄存器中

 

this指针可以为空吗? 

提问:下面这种情况,程序会报错、崩溃还是正常运行呢?

答案是:正常运行

下面这种情况呢?

答案是:崩溃

为什么第一个情况能正常运行,而第二个情况就会崩溃呢?

因为出现箭头并不一定会解引用,Func不在对象内部,也没有对空指针d1进行解引用,所以可以正常运行;而Init中进行了解引用,访问了空指针,所以崩溃。

是否解引用,取决于右边要访问的东西在不在对象内部,而不是根据符号判断。

完.

 

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

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

相关文章

Folx Pro Mac中文p破解版如何使用?为您带来Folx Pro 详细使用教程!

​ Folx pro 5 中文版是mac上一款功能强大的老牌加速下载软件,新版本的Folx pro整体界面非常的简洁和漂亮,具有非常好用的分类管理功能,支持高速下载、定时下载、速度控制、iTunes集成等功能。Folx pro兼容主流的浏览器,不但可以下…

什么是媒体发稿?发稿媒体分类及发稿流程

传媒如春雨,润物细无声,大家好,我是51媒体网胡老师。 媒体发稿是一种企业推广和宣传的手段,通过媒体渠道传递企业信息和形象。 媒体发稿的含义在于,当企业有新闻、事件或其他消息需要对外公布时,可以选择…

氢氟酸在晶圆厂中的应用与防护

氢氟酸,这种剧毒液体竟然会被用在晶圆的生产中,这个可能让你匪夷所思。实际上,氢氟酸这种看似普通的清澈液体,实则在芯片生产中扮演了至关重要的角色。 氢氟酸的性质? 氢氟酸(Hydrofluoric acid&#xff0c…

【VSCode】解决VSCode远程连接问题:远程主机可能不符合 glibc 和 libstdc++

今天用VSCode进行ssh连接时,提示“远程主机可能不符合 glibc 和 libstdc VSCode 服务器的先决条件”。查了一下发现这个问题主要是由于VSCode在一月份发布的最新版本v1.86中要求远程主机 glibc>2.28导致的,所以ssh连接Ubuntu 18.04的时候就会提示这个…

AI之T2I:Stable Diffusion 3的简介、安装和使用方法、案例应用之详细攻略

AI之T2I:Stable Diffusion 3的简介、安装和使用方法、案例应用之详细攻略 目录 Stable Diffusion 3的简介 1、效果测试 官方demo 网友提供 Stable Diffusion 3的安装和使用方法 1、安装 2、使用方法 Stable Diffusion 3的案例应用 1、基础案例 Stable Diff…

jmeter 测试数据库的详细方法

当前版本: jmeter 5.6.3mysql 5.7.39 简介 JMeter是一个功能强大的开源性能测试工具,它被广泛用于测试Web应用程序、Web服务、API、数据库以及其他类型的应用程序。支持测试数据库的性能和可靠性,可以模拟多个并发用户对数据库执行各种不同类…

react中修改state中的值无效?

// 初始化state state {personArr:[{name:张三,id:1},{name:李四,id:2},{name:王五,id:3}] }componentDidMount(){const newName 赵六const indexUpdate 1const newArr this.state.personArr.map((item,index)>{if(indexUpdate index){return {...item,name:newName}}e…

二阶低通滤波器(博途PLC SCL源代码)

在学习滤波器之前我们先了解下截止频率的准确定义,周期正弦信号经过传递函数后的输出信号,其幅值衰减-3dB时对应的频率。-3dB的含义是幅值衰减为原来的约0.707。更多滤波器信号处理相关内容请参看下面文章链接: 1、PLC一阶低通滤波器 https://rxxw-control.blog.csdn.net/…

174基于matlab的雷达数字信号处理

基于matlab的雷达数字信号处理。该程序具备对雷达目标回波的处理能力,能够从噪声中将目标检测出来,并提取目标的距离、速度、角度信息。有相应的试验文档。程序已调通,可直接运行。 174 雷达数字信号处理 目标检测出来 (xiaohongshu.com)

java数据结构与算法刷题-----LeetCode700. 二叉搜索树中的搜索

java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.csdn.net/grd_java/article/details/123063846 文章目录 1. 法一:递归2. 法二:迭代法 解题思路:时…

Qt RGB三色灯上位机

今天突发奇想做一个Qt RGB三色灯上位机,刚好手上有一个RGB三色灯和arduion开发板。 我是想实现一个颜色选择器界面然后鼠标点击颜色区域就可以发出rgb的值,然后把这个值通过串口线发送给arduion,arduion再解析出数据发送给RGB三色灯。 实现界面如下&…

STM32单片机基本原理与应用(九)

SDIO/SD卡实验 实验内容 将SD卡插入实训平台并烧写程序,开机后TFTLCD屏幕上会显示是否成功初始化SD卡并显示SD卡容量。 电路原理图 实验原理 SD卡的通信方式有两种:SPI和SDIO。SD卡有五种寄存器,如下表 SD 卡的指令由 6 个字节组成&…

Programming Abstractions in C阅读笔记:p293-p302

《Programming Abstractions in C》学习第73天,p293-p302总结,总计10页。 一、技术总结 1.时间复杂度 (1)quadratic time(二次时间) p293, Algorithms like selection sort that exhibit O(N^2) performance are said to run in quadratic time。 2…

Go Run - Go 语言中的简洁指令

原文:breadchris - 2024.02.21 也许听起来有些傻,但go run是我最喜欢的 Go 语言特性。想要运行你的代码?只需go run main.go。它是如此简单,我可以告诉母亲这个命令,她会立即理解。就像 Go 语言的大部分功能一样&…

软件运维维保方案-套用文档

软件运维维保方案 项目情况 1.1 项目背景 简述项目的来源、目的和重要性。 说明项目的规模、预算和预期目标。 1.2 项目现状 分析当前系统/软件的运行状态、存在的问题和潜在风险。 提供最近一次的维护报告或相关统计数据。服务简述 2.1 服务内容 明确运维服务的具体内容&…

当我拥有1PB的磁盘

在开始之前可以先看一下我的有关文件传输协议的博文。 因为今天会涉及到WebDAV文件传输协议。 未来会有关于个人NAS系统和软路由的相关文章大家可以关注一下。 原文地址:当我拥有1PB的磁盘 - Pleasure的博客 下面是正文内容: 前言 话不多说直接看效…

istio实战:springboot项目在istio中服务调用

目录 一、前言二、准备工作三、问题排查四、总结参考资料 一、前言 在经过前面几天k8s和Istio的安装之后,开始进入最核心的阶段。微服务在抛弃传统的服务注册和服务发现之后,是怎么在istio怎么做服务间的调用的呢?本次实战花费了我2-3天的时…

ArcgisForJS如何使用ArcGIS Server发布的GP服务?

文章目录 0.引言1.ArcGIS创建GP服务2.ArcGIS Server发布GP服务3.ArcgisForJS使用ArcGIS Server发布的GP服务 0.引言 ArcGIS for JavaScript(或简称AGJS)是一个强大的工具,它允许开发者使用JavaScript在Web浏览器中创建和运行ArcGIS应用程序。…

如何对CODESYS开发系统的选项进行配置(1)

CFC Editor CFC Editor 的参数会影响CFC编辑器的外观和功能。 CFC Editor 参数 CFC Editor 的参数分成了4个类别,分别是General、View、Print和Monitoring。 一、General类别 General类别里是CFC Editor编辑器的一般参数,目前只有一个参数:En…

蓝桥杯备战刷题(自用)

1.被污染的支票 #include <iostream> #include <vector> #include <map> #include <algorithm> using namespace std; int main() {int n;cin>>n;vector<int>L;map<int,int>mp;bool ok0;int num;for(int i1;i<n;i){cin>>nu…