C++(类和对象上篇)

news2024/11/23 21:25:55

本节目标:

1.面向过程和面向对象初步认识
2.类的引入
3.类的定义
4.类的访问限定符及封装
5.类的作用域
6.类的实例化
7.类的对象大小的计算
8.类成员函数的this指针
 


目录

1、面向过程和面向对象初步认识 

2、类的引入 

4.类的访问限定符及封装 

4.1访问限定符 

4.1.1访问限定符说明

4.2封装 

5.类的作用域 

 7.类对象模型

7.1如何计算类对象大小 

7.2类对象的存储方式猜测 

7.2.1对象中包含类的各个成员 

7.2.2代码只保存一份,在对象中保存存放公共代码的地址

7.2.3只保存成员变量,成员函数存放在公共代码区 

7.3结构体内存对齐规则 

8.this指针 

 8.1this指针的引出

8.2this指针的特性 



1、面向过程和面向对象初步认识 

c语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题 

c++是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间交互完成。

   我们可以用洗衣服这个例子将,面向过程和面向对象解释清楚。

2、类的引入 

 在讲类之前,我们回顾一下,c语言中结构体的知识,结构体可以定义变量,所以我们在实现栈的时候,利用结构体实现数组栈,在c++中,祖师爷觉得光定义变量无法满足使用,于是将结构体内除了可以定义变量,还增加了函数,并将它命名成类,兼容c语言,struct也升级成了类,也可以定义函数,可以把栈的初始化,进栈,出栈,销毁等都写成函数,放进结构体内部,如下所示:

typedef int DataType;
struct Stack
{
void Init(size_t capacity)
{
_array = (DataType*)malloc(sizeof(DataType) * capacity);
if (nullptr == _array)
{
perror("malloc申请空间失败");
return;
}
_capacity = capacity;
_size = 0;
}
void Push(const DataType& data)
{
// 扩容
_array[_size] = data;
++_size;
}
DataType Top()
{
return _array[_size - 1];
}
void Destroy()
{
if (_array)
{
free(_array);
_array = nullptr;
_capacity = 0;
_size = 0;
}
}
DataType* _array;
size_t _capacity;
size_t _size;
};
int main()
{
Stack s;
s.Init(10);
s.Push(1);
s.Push(2);
s.Push(3);
cout << s.Top() << endl;
s.Destroy();
return 0;
}

这样写虽然优化了,结构体内部可以放置成员函数,但是,对于成员变量我们还是可以访问修改,不够安全,就比如我们想访问栈内共多少元素的代码:

return _array[_size - 1];

我们是根据访问成员变量size的数值来检测栈内元素,但是size这个变量可以被修改,导致数据不准确。于是c++中新增了访问限定符及封装。

4.类的访问限定符及封装 

4.1访问限定符 

 C++实现封装的方式:用类将对象的属性与方法结合在一块,让对象更加完善,通过访问权限选
择性的将其接口提供给外部的用户使用。

 

4.1.1访问限定符说明

 1. public修饰的成员在类外可以直接被访问
2. protected和private修饰的成员在类外不能直接被访问(此处protected和private是类似的)
3. 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
4. 如果后面没有访问限定符,作用域就到 } 即类结束。
5. class的默认访问权限为private,struct为public(因为struct要兼容C)

 注意:访问限定符只在编译时有用,当数据映射到内存后,没有任何访问限定符上的区别。

4.2封装 

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

 封装本质上是一种管理,让用户更方便使用类。比如:对于电脑这样一个复杂的设备,提供给用户的就只有开关机键、通过键盘输入,显示器,USB插孔等,让用户和计算机进行交互,完成日常事务。但实际上电脑真正工作的却是CPU、显卡、内存等一些硬件元件。

在C++语言中实现封装,可以通过类将数据以及操作数据的方法进行有机结合,通过访问权限来隐藏对象内部实现细节,控制哪些方法可以在类外部直接被使用
 

5.类的作用域 

 类定义了一个新的作用域,类的所有成员都在类的作用域中,在类体外定义成员时,需要使用::作用域操作符知名成员属于那个类域。

class Person
{
public:
	void PrintPersonInfo();
private:

	char _name[20];
	int _age;
	int _gender[3];
};
// 这里需要指定PrintPersonInfo是属于Person这个类域
void Person::PrintPersonInfo()
{
	cout << _name << " " << _gender << "" << _age << endl;
}

6.类的实例化

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

1.类相当于建房子的图纸,他规定了房子的大小,需要使用的器材,位置摆放,但是没有实际实物,用类创造的对象就相当于用图纸建造房子,这个就叫类的实例化。

2.用图纸也可以建造不同的房子,同样,一个类可以实例化多个对象,实例化的对象占用实际的物理空间,存储类成员变量。

int main()
{
  Person._age = 19;//编译错误
  return 0;

}

用类是无法访问成员变量的,类就是个图纸,没有实际空间,只有实例化出对象也就是房子,才能实际存储东西。

 7.类对象模型

7.1如何计算类对象大小 

class A
{
public:
void PrintA()
{
cout<<_a<<endl;
}
private:
char _a;
};

 

类的定义包含成员函数和成员变量,那么类的大小该是多少呢?

7.2类对象的存储方式猜测 

7.2.1对象中包含类的各个成员 

 

这样存储的缺点:每个对象的成员变量是不同的,但是都会共用同一份函数,如果用这种存储,当类创建不同对象时候,每一份代码中都会保存相同代码很多次,很浪费空间,那么能不能让共用的代码只保存一次呢?

7.2.2代码只保存一份,在对象中保存存放公共代码的地址

 

7.2.3只保存成员变量,成员函数存放在公共代码区 

 

我们可以通过不同对象分别获取大小来判断计算机到底是按照那种方式存储。代码如下:

//代码1 类中既有成员变量,又有成员函数
class A1 {
public:
void f1(){}
private:
int _a;
};

//代码2 类中仅有成员函数
class A2 {
public:
void f2() {}
};

// 代码3类中什么都没有---空类
class A3
{};

 sizeof(A1), sizeof(A2), sizeof(A3)分别是多少呢?

 

    成员函数以及空类是占用一个字节的,这个是为了占位,表示对象的存在。通过对对象大小的计算,我们得出结论,成员函数是存在公共代码区的。

7.3结构体内存对齐规则 

c++中结构体内存对齐和c一样,注意以下几点:

 1. 第一个成员在与结构体偏移量为0的地址处。
2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
注意:对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值
VS中默认的对齐数为8
3. 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍
4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整
体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

 

8.this指针 

 8.1this指针的引出

我们通过一段日期类的代码,将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 s1;
	Date s2;
	s1.Init(2023, 04, 12);
	s2.Init(2023, 04, 13);
	s1.Print();
	s2.Print();
	return 0;
}

 对于上述代码,我们思考一个问题,Init和Print两个成员函数,函数体中没有关于不同对象的区分,那么,当s1调用Init函数时,该函数如何知道应该设置d1对象,而不是设置d2对象呢?

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

 

8.2this指针的特性 

 1. this指针的类型:类类型* const,即成员函数中,不能给this指针赋值
2. 只能在“成员函数”的内部使用
3. this指针本质上是“成员函数”的形参,当对象调用成员函数时,将对象地址作为实参传递给
this形参。所以对象中不存储this指针。
4. this指针是“成员函数”第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传
递,不需要用户传递

 问题:this指针可以为空吗?

我们通过下面两道题来回答这个问题?

// 1.下面程序编译运行结果是? A、编译报错 B、运行崩溃 C、正常运行
class A
{
public:
void Print()
{
cout << "Print()" << endl;
}
private:
int _a;
};
int main()
{
A* p = nullptr;
p->Print();
return 0;
}
// 1.下面程序编译运行结果是? A、编译报错 B、运行崩溃 C、正常运行
class A
{
public:
void PrintA()
{
cout<<_a<<endl;
}
private:
int _a;
};
int main()
{
A* p = nullptr;
p->PrintA();
return 0;
}

 

 代码1:

代码2: 

 

 

 

 

 

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

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

相关文章

为了做低代码平台,这些年我们对.NET的DataGridView做的那些扩展

我们的低代码开发平台从一开始决定做的时候&#xff0c;就追求未来能够支持多种类型的客户端&#xff0c;目前支持Winform&#xff0c;Web&#xff0c;H5&#xff0c;FlutterAPP&#xff0c;当然了&#xff0c;未来也有可能会随着实际的需要淘汰掉一些客户端的。 为了系统更易…

springboot - 实现动态刷新配置

自定义的配置数据源&#xff0c;继承自Spring框架的 MapPropertySource 类&#xff0c;从一个名为 my.properties 的文件中读取配置信息&#xff0c;并在每10秒钟刷新一次。 这里不加Component&#xff0c;是因为&#xff1a; FilePropertiesSource filePropertiesSource new…

辨析 总结PMP各种BS结构

OBS 组织分解结构、BOM 物料清单、WBS工作分解结构、RBS 资源分解结构、RBS 风险分解结构、RAM 责任分匹配矩阵辨析 组织分解结构 OBS&#xff08;Organizational Breakdown Structure&#xff09; 描述了执行组织的层次结构&#xff0c;以便把工作包同执行组织单元相关联 物料…

电子邮件SDK:MailBee.NET 12.3.1 Crack

MailBee.NET 对象捆绑包包括SMTP、POP3、IMAP、EWS、安全、反垃圾邮件、Outlook 转换器、地址验证器、PDF组件以及BounceMail、HTML、MIME、ICalVCard组件&#xff0c;这些组件是一项常用功能。 MailBee.NET Objects是一组强大且功能丰富的 .NET 组件&#xff0c;用于创建、发送…

Haffman编码(算法导论)

上次算法导论课讲到了Haffman树&#xff0c;笔者惊叹于Haffman编码的压缩效果&#xff0c;故想自己亲自动手尝试写一个极简的Haffman压缩程序。 首先&#xff0c;我们来了解一下什么是Haffman编码 Haffman编码 赫夫曼编码可以很有效地压缩数据&#xff1a;通常可以节省20%&am…

UNIX环境高级编程——进程关系

9.1 引言 本章详细说明进程组以及会话的概念&#xff0c;还将介绍登录shell&#xff08;登录时所调用的&#xff09;和所有从登录shell启动的进程之间的关系。 9.2 终端登录 9.3 网络登录 9.4 进程组 每个进程除了有一进程ID之外&#xff0c;还属于一个进程组&#xff0c;进…

一曲微茫度余生 ——川剧《李亚仙》唱响香港西九戏曲中心

2023年4月28日晚&#xff0c;香港西九戏曲中心灯火辉煌。重庆市川剧院携手成都市川剧研究院带来的川剧《李亚仙》首场演出在这个为戏曲而设的世界级舞台重磅上演。 此次访演受香港西九戏曲文化中心的邀请&#xff0c;原重庆市文化和旅游发展委员会党委书记、主任刘旗带队&…

『LogDashboard』.NET开源的日志面板——登录授权页面扩展

&#x1f4e3;读完这篇文章里你能收获到 了解LogDashboard扩展开源项目——LogDashboard.Authorization掌握LogDashboard扩展内置登录页的使用方式 文章目录 一、LogDashbaord介绍1. 功能支持2. 快速开始 二、LogDashboard.Authorization1. 功能介绍2. 项目接入3. 更多示例 一…

Python语法学习

目录 Openmv用micro python开发的原因 print函数 列表 元组 判断 if...else... if...elif...else 循环 for循环 while循环 强制类型转换 点灯之路 点个不同颜色的闪烁LED 本文章仅作为个人的Openmv学习笔记&#xff0c;有问题欢迎指正~ Openmv用micro python开发…

【MPC|云储能】基于模型预测控制(MPC)的微电网调度优化的研究(matlab代码)

目录 1 主要内容 2 程序难点及问题说明 3 部分程序 4 下载链接 1 主要内容 该程序分为两部分&#xff0c;日前优化部分——该程序首先根据《电力系统云储能研究框架与基础模型》上面方法&#xff0c;根据每个居民的实际需要得到响应储能充放电功率&#xff0c;优化得到整体…

性能测评:阿里云服务器ECS通用型g8i实例CPU内存安全存储

阿里云服务器ECS通用型实例规格族g8i采用2.7 GHz主频的Intel Xeon(Sapphire Rapids) Platinum 8475B处理器&#xff0c;3.2 GHz睿频&#xff0c;g8i实例采用阿里云全新CIPU架构&#xff0c;可提供稳定的算力输出、更强劲的I/O引擎以及芯片级的安全加固。阿里云百科分享阿里云服…

真题详解(DNS)-软件设计(六十三)

真题详解&#xff08;有向图&#xff09;-软件设计&#xff08;六十二)https://blog.csdn.net/ke1ying/article/details/130443040 顺序存储&#xff1a;元素和存储空间相对位置来表示数据元素之间逻辑关系。 RFB&#xff1a;远程访问图形用户界面的简单协议。 在ISO/IEC9126软…

【五一创作】跑alpaca-lora语言模型的常见问题(心得)

训练部署alpaca-lora语言模型常见问题 Alpaca-Lora是一个开源的自然语言处理框架&#xff0c;使用深度学习技术构建了一个端到端的语言模型。在训练和部署alpaca-lora语言模型时&#xff0c;可能会遇到一些常见问题。本文将介绍一些这些问题及其解决方法。 1. bitsandbytes版…

计算机视觉毕业后找不到工作怎么办?怒刷leetcode,还是另寻他路?

文章目录 一、计算机视觉毕业后找不到工作怎么办&#xff1f;二、大环境&#xff1a;前两年的泡沫太大三、还是要把自己的基本功搞扎实&#xff0c;真正的人才什么时候都紧缺四、转换思路&#xff0c;另投他坑五、要有毅力&#xff0c;心态放平六、最后的建议 一、计算机视觉毕…

Python毕业设计之django社区报修维修预约上门服务系统

开发语言&#xff1a;Python 框架&#xff1a;django Python版本&#xff1a;python3.7.7 数据库&#xff1a;mysql 数据库工具&#xff1a;Navicat 开发软件&#xff1a;PyCharm 目 录 摘 要 I Pick to II 1绪论 1 1.1项目研究的背景 1 1.2开发意义 1 1.3项…

「数据架构」介绍下一代主数据管理(MDM)

主数据管理是旨在创建和维护权威、可靠、可持续、准确、及时和安全的环境的过程和技术框架。这个环境代表了一个单一版本的事实&#xff0c;作为跨不同的系统、业务单元和用户社区的可接受的记录系统。 尽管MDM不是新的&#xff0c;但是最近人们对开发MDM解决方案的兴趣大增。这…

正则表达式 Regular Expression

情景引入改代码查找文件词法分析器网站注册密码信息爬取 简介在线测试工具RegulexRegExr 语法普通字符非打印字符特殊字符限定符定位符修饰符元字符 实例匹配邮箱 情景引入 改代码 修改代码格式问题&#xff0c;或者重命名代码里的某个变量等&#xff0c;都可以使用 VS Code …

Mysql 管理

目录 0 课程视频 1 系统数据库 -> 安装完mysql ->自带四个数据库 2 常用工具 -> 写脚本用 2.1 mysql 客户端工具 2.2 mysqladmin 2.3 mysqlbinlog -> 二进制日志 -> 运维讲解 2.4 mysqlshow 2.5 mysqldump 备份用 ->导出 2.6 mysqlimport/source -…

一篇带你了解大厂都在用的DDD领域驱动设计

一、DDD到底是什么 DDD全称Domain Driven Design&#xff0c;领域驱动设计。 为了解决快速变化、复杂系统的设计问题的 领域驱动设计是Eric Evans在2004年发表的Domain Driven Design&#xff08;领域驱动设计&#xff0c;DDD)著作中提出的一种从系统分析到软件建模的一套方…

K8s基础2——部署单Master节点K8s集群、切换containerd容器运行时

文章目录 一、部署K8S集群方式二、kubeadm工具搭建K8s集群2.1 资源配置2.2 服务器规划2.3 搭建流程2.3.1 操作系统初始化2.3.2 使用docker容器引擎2.3.3 安装cri-dockerd2.3.4 安装kubeadm&#xff0c;kubelet和kubectl2.3.5 master节点初始化2.3.6 加入node节点2.3.7 部署容器…