[C++]类与对象(上)

news/2025/1/16 2:40:13 标签: c++, 开发语言

目录

 💕1.C++中结构体的优化

 💕2.类的定义

💕3.类与结构体的不同点

💕4.访问限定符(public,private,protected)

 💕5.类域

💕6.类的实例化 

💕7.类的字节大小

💕8.类的字节大小特例

 💕9.this指针


  

 (最新更新时间——2025.1.14,更新内容 目录9)

因为困难多壮志,不教红尘惑坚心

        今身暂且栖草头,他日狂歌踏山河

 💕1.C++中结构体的优化

在C++中,结构体的使用得到了优化,具体优化了什么呢?请看以下代码->:

struct student
{
	int age;
	double num;
};

int main()
{
	struct student s1;//C语言中书写,C++也兼容
	student s1;//C++中优化
	return 0;
}

我们在C语言中书写时,需要把struct把写上,而在C++中得到了优化,不需要写struct,直接写结构体的名称也可以使用


同时我们也可以在struct中定义函数

struct student
{
	int age;
	double num;
	int add(int a, int b)
	{
		return a + b;
	}
};

int main()
{
	student s1;//C++中优化
	cout<<s1.add(10, 20);//输出30
	return 0;
}


 💕2.类的定义

我们回到正题,什么是类?

类其实就是结构体的优化,我们将struct 更改为 class,就属于变为了类


先看一段代码,在这串代码中,class 是类的关键字,student 是类的名字

{ }为类的主体,类中的变量称为类的属性或成员变量,

class student
{    
    //类的⽅法或者成员函数
	int add(int a, int b)
	{
		return a + b;
	}

    //类的属性或者成员变量
	int age;
	double num;
};

int main()
{
	student s1;//创建类变量s1
}

就此看来,类与结构体还没有不同点,那么不同点在哪呢?

💕3.类与结构体的不同点

类中的成员函数是与成员变量密切相关的,即同一类中,成员函数可以给成员变量赋值,并且成员变量也可以作为成员函数的参数,我们举个例子->:

如图所示,即使我们不进行传参,成员函数内也可以找到类中对应的成员变量,而结构体却不可以

因此->:在类中创建的成员变量,在类中是直接可以用的

💕4.访问限定符(public,private,protected)

在C++中,类的定义中新建了三种权限关系,分别是public,private,与protected

这些的意义是什么呢?


C++⼀种实现封装的⽅式,⽤类将对象的属性与⽅法结合在⼀块,让对象更加完善,通过访问权限

选择性的将其接⼝提供给外部的⽤⼾使⽤

public修饰的成员在类外可以直接被访问;protected和private修饰的成员在类外不能直接被访 问,protected和private是⼀样的,以后继承章节才能体现出他们的区别,接下来是代码举例->:

我们可以发现,我们在类中的成员函数设置为private,只可以在类的内部使用,那么在类的外部就不能使用这些成员函数,这就是private的作用


那如果把它换成public呢?

效果如下->:更换成public后,权限被更改为公有的,在类外面也可以进行使用


如果我们访问限定符什么都不写的话,系统会默认全部设为private


 💕5.类域

讲类域之前,我们先讲一个简单的例子

class student
{
	int age;
	int year;
};
int main()
{
	
}

这是的类叫做类的声明还是定义?


答案是声明,类的定义是会开创出空间的,而此时的类没有任何的变量并不会开创空间,所以此时叫做类的定义,那既然是类的定义,那可不可以写在 .h 文件中,答案是可以的,接下来请看代码->:


.h文件>:

#pragma once
#include<iostream>
#include"abc.h"
using namespace std;

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

我们可以在.h中实现类的声明,那类中成员函数的实现怎么办,我们以往的经验是写在函数功能实现的.c文件中,在C++中也是一样的,只不过有一点不同


函数实现文件.c->:

#define _CRT_SECURE_NO_WARNINGS 
#include"achie.h"

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

在这些代码中,我们看到了类中成员函数的实现,有许多人都会注意到了 Date:: ,这是什么意思?这是因为类域的存在,我们知道函数的实现依靠的是函数的地址,而编译器寻找的方式是全局域,局部域,命名作用域与类域,我们的Init写在了类域中,编译器在全局域与局部域都找不到,而命名作用域与类域都是需要特殊指定的域,所以如果不声明编译器就找不到这个函数在哪,我们可以试一下不指定后的样子:


以下分别是.h与函数实现的.c文件中的图片,可以看到.h中说明找不到函数的定义,因为在函数实现.c文件中,并没有找到Init函数的地址

💕6.类的实例化 

类是对象进⾏⼀种抽象描述,是⼀个模型⼀样的东西,限定了类有哪些成员变量,这些成员变量只 是声明,没有分配空间,⽤类实例化出对象时,才会分配空间
⼀个类可以实例化出多个对象,实例化出的对象 占⽤实际的物理空间,存储类成员变量。打个⽐ ⽅:类实例化出对象就像现实中使⽤建筑设计图建造出房⼦,类就像是设计图,设计图规划了有多 少个房间,房间⼤⼩功能等,但是并没有实体的建筑存在,也不能住⼈,⽤设计图修建出房⼦,房 ⼦才能住⼈。同样类就像设计图⼀样,不能存储数据,实例化出的对象分配物理内存存储数据。

一个类可以实例出多个对象的代码演示->:

#define _CRT_SECURE_NO_WARNINGS 
#include<iostream>
using namespace std;

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

int main()
{
	Date a1;
	Date a2;
	Date a3;
}

这里就是类与对象的关系,一个类可以有多个对象,如果有拿这段代码去运行而报错的同志,那就是因为对象创建出来后没有手动初始化,注意是手动(后面讲)

💕7.类的字节大小

类的字节大小是怎么计算的,其实与我们在C语言中学的结构体极其类似,具体在哪不同,我们接着看->:

我们可以看到是12个字节,为什么?

其实这里与我们在C语言中学习的结构体内存存储方式基本相同,如果不懂的具体请看这篇文章,我们这里只讲不同点->:

C语言结构体详解(超全)简单易懂(代码+万字文字+画图讲解)


不同点在于->:当我们计算类的字节大小时,我们会思考,类中的函数存储在哪?

⾸先函数被编译后是⼀段指令,对象中没办法存储,因此这些指令存储在⼀个单独的区域(代码段)

也就是说明类中的成员函数存储在公共代码区,这也意味着每个对象所使用的函数是共同的,并不会因为每有一个类就创建一个它自己的函数,它与其他对象所使用的函数是共同的


我们知道,函数的使用是相当频繁地,如果一个对象使用100次函数,那么创建出来的空间是非常大的,因此函数的地址会存放在公共代码区,避免空间重复,浪费空间


注意->:对象中的每个成员变量是独立的成员变量

💕8.类的字节大小特例

为什么输出的字节是1呢?

类中的成员变量为空,不应该输出0吗?

其实这个1字节是为了识别出类而开辟的,所以是1


那这样呢?

这样输出的1跟之前所输出1的原因是相同的,都是为了识别出类的存在

 💕9.this指针

在类中的每一个成员函数中,其实都有一个隐藏的 this 指针,什么是隐藏的 this 指针?

当我们调用类中的成员函数时,会将这个对象的地址传输过去,什么意思?请看代码->:

在我们调用函数时,就会将对象的地址传输过去,并在成员函数的形参处用Date* const this来接受,为什么会报错?这是因为->:


C++规定不能在实参和形参的位置显⽰的写this指针(编译时编译器会处理),但是可以在函数体内使⽤this指针,什么意思?请看下图->:


这里的this可以写也可以不写,主要是为了演示一遍,这里的this指的就是对象a1的地址


小题思考->:

我们思考一下,下面这串代码的运行结果是什么->:

#include<iostream>
using namespace std;
//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,也就是一级指针,传空指针是没有问题的,空指针只有在解引用时候才会报错,而这里并没有进行解引用,也就是说会正常运行


再来看一道
 

#include<iostream>
using namespace std;
//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;
}

这道题就不会正常运行了,而是运行崩溃,因为从语法上看,this->a 等价于 (*this).a。这里的 *this 就是对 this 指针的解引用,它获取了 this 所指向的对象本身,然后通过 . 操作符访问该对象的成员变量 a

空指针被解引用了,所以运行崩溃了


最后一道思考->:

3. this指针存在内存哪个区域的 ()
A. 栈 B.堆 C.静态区 D.常量区 E.对象⾥⾯

这里的答案是栈区,因为this指针是形参,而形参是存储在栈区的


http://www.niftyadmin.cn/n/5824572.html

相关文章

MySQL中的合并函数

一、group_concat MySQL的GROUP_CONCAT函数是一种强大的聚合函数&#xff0c;通常用于将多个行合并为一个字符串。 group_concat(DISTINCT 要连接的字段 Order BY ASC/DESC排序字段 Separator分隔符) 在合并之时对合并的数据排序&#xff0c;可以确定在拆解合并后的字段后&a…

九 RK3568 android11 MPU6500

一 MPU6500 内核驱动 1.1 查询设备连接地址 查看原理图, MPU6500 I2C 连接在 I2C4 上, 且中断没有使用 i2c 探测设备地址为 0x68 1.2 驱动源码 drivers/input/sensors/gyro/mpu6500_gyro.c drivers/input/sensors/accel/mpu6500_acc.c 默认 .config 配置编译了 mpu6550 …

人工智能任务19-基于BERT、ELMO模型对诈骗信息文本进行识别与应用

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下人工智能任务19-基于BERT、ELMO模型对诈骗信息文本进行识别与应用。近日&#xff0c;演员王星因接到一份看似来自知名公司的拍戏邀约&#xff0c;被骗至泰国并最终被带到缅甸。这一事件迅速引发了社会的广泛关注。该…

Oracle EBS GL定期盘存WIP日记账无法过账数据修复

系统环境 RDBMS : 12.1.0.2.0 Oracle Applications : 12.2.6 问题症状 用户反映来源为“定期盘存”和类别为“WIP”的日记账无法过账,标准日记账的界面上的过账按钮灰色不可用。但是,在超级用户职责下,该日记账又可以过账,细心检查发现该业务实体下有二个公司段值15100和…

三小时深度学习PyTorch

【对新手非常友好】三小时深度学习PyTorch快速入门&#xff01;包教会你的&#xff01; --人工智能/深度学习/pytorch_哔哩哔哩_bilibili从头开始&#xff0c;把概率论、统计、信息论中零散的知识统一起来_哔哩哔哩_bilibili从编解码和词嵌入开始&#xff0c;一步一步理解Trans…

【免费开源】积木JimuBI大屏集成eladmin

JimuBI介绍 JimuBI 是一个JAVA语言的低代码数据可视化大屏BI产品&#xff0c;将大屏、仪表盘、移动面板、图表或页面元素封装为基础组件&#xff0c;无需编写代码即可完成业务需求。 这是JeecgBoot团队出品的另外一款报表产品&#xff0c;积木报表已经成为业内报表首先&#x…

Android 调用系统服务接口获取屏幕投影(需要android.uid.system)

媒体投影 借助 Android 5&#xff08;API 级别 21&#xff09;中引入的 android.media.projection API&#xff0c;您可以将设备屏幕中的内容截取为可播放、录制或投屏到其他设备&#xff08;如电视&#xff09;的媒体流。 Android 14&#xff08;API 级别 34&#xff09;引入…

微信小程序获取当前页面路径,登录成功后重定向回原页面

&#x1f935; 作者&#xff1a;coderYYY &#x1f9d1; 个人简介&#xff1a;前端程序媛&#xff0c;目前主攻web前端&#xff0c;后端辅助&#xff0c;其他技术知识也会偶尔分享&#x1f340;欢迎和我一起交流&#xff01;&#x1f680;&#xff08;评论和私信一般会回&#…