C++57个入门知识点_17 类的访问权限及C语言模拟类的封装(类的私有权限突破方法:编译期进行权限检查,运行期通过指针修改类的私有成员变量;利用函数指针对结构体中成员变量进行修改;CPU大小尾排列)

接上篇:C++57个入门知识点_16 类的标准写法(类名、成员变量、成员函数及对象命名规则;成员变量一般为私有,成员函数为公有并暴露给外部使用成员变量;防止类过大,声明写在.h,实现写在.cpp,调用.h)。前面两篇介绍了面向对象的语言的特点、一个类应该怎样去写、访问权限,本篇将会讲 类的访问权限及C语言模拟类的封装。
总结:
1.类的访问权限及突破方法:
(1) 类的访问权限检查是在编译器进行的;在编译时期对访问权限进行限制,在程序运行时期可以进行修改;
(2)在运行期间可以通过指针修改内存值:*(int*)&clock = 111;
2. 利用函数指针在C语言中模拟类的封装: 利用函数指针typedef void((*PFN_SetHour)(int n));对结构体中的成员变量进行修改(可以用来感悟成员函数是属于整个类的)

1. 类的访问权限及突破方法


类的访问权限检查是在编译器进行的;在编译时期对访问权限进行限制,在程序运行时期可以进行修改

前面已知private只有在类域内可以访问,我们要讨论一个问题,访问的权限有没有办法突破呢?

下面为上篇中的代码,我们已经知道clock.m_nHour=1;在编译时是无法通过的,但是当程序运行之后,对象clock`是存在于内存中的,因此是否可以操作内存来修改对象的私有成员变量呢?

#include <iostream>

class CClock {
private:
	int m_nHour;
	int m_nMinute;
	int m_n_Second;

public:
	void SetHour(int nHour)
	{
		if (nHour >= 24 && nHour < 0)
		{
			return;
		}
		m_nHour = nHour;
	};
};

int main(int argc, char* argv[])
{
	CClock clock;
	clock.m_nHour=1;
	return 0;
}

1.1 通过调试器修改内存值


下面的代码给类的私有成员变量赋初值,通过内存去查看对象中成员变量的值,并通过调试器对内存中得值进行修改。

#include <iostream>

class CClock {

private:
	int m_nHour=1;
	int m_nMinute=2;
	int m_n_Second=3;

public:
	void SetHour(int nHour)
	{
		if (nHour >= 24 && nHour < 0)
		{
			return;
		}
		m_nHour = nHour;
	};
};

int main(int argc, char* argv[])
{
	CClock clock;
	return 0;
}

运行之后:内存中可以看到,私有变量具有初始值
在这里插入图片描述

1.2 CPU内存中大小尾排列方式

大家可能看到了,在内存中m_nHour的值是按照01 00 00 00排列的,而不是我们在二进制排列00 00 00 01,这是由于CPU的大小尾的关系相关,上面显示的是Intel CPU的方式。

大尾方式 即低地址数据在低位,高地址数据在高位(低低高高的排列方式),01 00 00 00四个数据对应地址分别为0x004FFA50 0x004FFA51 0x004FFA52 0x004FFA53

1.3 运行中通过指针修改内存值

在程序运行时,我们可以通过调试器修改内存中值。
在这里插入图片描述
那么我们是否可以代码方式在程序运行时修改内存,应该也是可以的。这样做的前提时你需要知道类在内存中占用多少字节?
类中包含3个int类型数据,但是类除了数据之外,还会有对齐值等影响类在内存中占用的字节数,此处不要求掌握。
一种简单的方法,使用int nSize = sizeof(clock);来编译时查看变量等在内存中占用的字节数。
对代码修改后可以看到,clock对象占用字节数为12,且m_nHour所在地址为首地址。
在这里插入图片描述
突破访问权限的方法:

//如何突破类的限制访问类的成员变量?常规语法不可以,可以通过指针的方式进行访问
//左侧含义,&clock取对象地址,(int*)&clock将地址强制准换为int指针,*(int*)&clock取指针下的内容
	*(int*)&clock = 111;

运行结果如下:对象clock中的私有成员变量在程序运行时改变
在这里插入图片描述

2. 利用函数指针在C语言中模拟类的封装

此处另外介绍一个小的知识点,我们通过C语言的方式,对手表进行封装,利用C语言模拟类的封装。C语言中结构体中是不可以增加行为的,但是我们又想将函数放入其中,如果放不了函数,我们可以将函数当做一种数据放入结构体中,数据即一种函数指针的方式

(1) 函数指针的定义方式: typedef void((*PFN_SetHour)(int n));
(2) 使用真实的函数地址给函数指针赋值方法: c1.pfnSetHour = SetHour;
(3) 函数指针的调用: c1.pfnSetHour(1);
(4) 为了修改对象中的变量的值将其对象的指针传入函数: void SetHour(struct taglock* c1,int n) {c1->nHour = n;}
(5) 修改结构体的变量值的方法: c1.pfnSetHour(&c1,1);

C++中编译器已经有了c1对象,相当于少传了一个&c1指针。

C语言中封装方法如下:

//封装:
#include <iostream>

//定义函数指针,相当于变量,需要赋值
typedef void((*PFN_SetHour)(int n));
//C语言模拟类的封装
struct taglock {

	int nHour;
	int nMinute;
	int n_Second;

	PFN_SetHour pfnSetHour;
};

//通过struct taglock* c1传入需要修改的目标,与结构体关联
void SetHour(struct taglock* c1,int n) {

	c1->nHour = n;

}

//调用函数
main()
{
struct taglock c1;
c1.pfnSetHour = SetHour;
//类似于类中成员函数的调用
c1.pfnSetHour(&c1,1);
}

上面的代码为伪代码的形式,可以用于理解,以下是我进行修改后的可以运行的代码:

//封装:
#include <iostream>

//结构体的前置声明,给函数指针中使用
struct taglock;

//定义函数指针,相当于变量,需要赋值
typedef void((*PFN_SetHour)(taglock*,int n));
//C语言模拟类的封装
struct taglock {

	int nHour;
	int nMinute;
	int n_Second;

	PFN_SetHour pfnSetHour;
};

//通过struct taglock* c1传入需要修改的目标,与结构体关联
void SetHour(struct taglock* c1, int n) {

	c1->nHour = n;

}

//调用函数
void main()
{
	struct taglock c1;
	c1.pfnSetHour = SetHour;
	//类似于类中成员函数的调用
	c1.pfnSetHour(&c1, 1);
}

3.视频学习地址:C++57个入门知识点_17 类的访问权限及C语言模拟类的封装

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

十月旧城

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值