C++ ---- 类和对象(上)

news2024/12/26 11:02:31

 

目录

本节目标

常见问题

面向过程和面向对象的理解

什么是类+如何定义类

类的引入

类的定义

类的两种定义习惯

类的作用域

类的访问限定符

访问限定符介绍

封装

封装的意义

类的实例化

 类对象模型

类对象的存储方式

结构体对齐

计算类对象的大小

this指针

 问题解答


本节目标

对面向对象有初步认识,能够正确的定义和使用类,了解类对象的存储方式,能够计算类的大小。清楚类该如何实例化,类的作用域等。对封装的概念、访问限定符,this指针有初步了解。

常见问题

1.this指针存在哪里?

2.this指针可以为空吗?

3.一个类的对象中包含了什么?

4.如何计算一个类的大小。

5.一个空类的大小?

6.什么是封装?

7.C++中struct和class的区别是什么?

答案在文章最后!!!

面向过程和面向对象的理解

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

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

什么是类+如何定义类

类的引入

在C语言中,通常用结构体描述一些值的集合,这些值称为成员变量。在C++中,结构体内不仅可以定义变量,还可以定义函数。除了struct zxy{};的定义方式,C++中引入了class关键字专门用来定义类,class zxy{}; 两种方式都是可以的,区别后面在讨论。

类的定义

struct和class为定义类的关键字,关键字后面接类名,{}为类的主体,类定义结束后的分号不能省略。类体中的内容包括成员变量(类的属性)和成员函数

struct

struct person1
{
	//成员函数
	//....
	//成员变量
	//....
};

class

class person2
{
	//成员函数
	//....
	//成员变量
	//.... 
};

类的两种定义习惯

声明和定义全部放在类体中

class Date
{
public:
	//函数声明和定义全部放在类体中
	void Fun()
	{
		//.....
	}
private:
	int _year;
	int _month;
	int _day;
};

类声明放在.h文件中,成员函数定义放在.cpp中。这种写法成员函数名前需要加类名::

.h中只有函数的声明

class Date
{
public:
	//函数声明和定义全部放在类体中
	void Fun1();
	void Fun2();
	void Fun3();

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

.cpp中写函数的定义

void Date::Fun1()
{
	//...
}
void Date::Fun2()
{
	//...
}
void Date::Fun3()
{
	//...
}

类的作用域

类定义了一个作用域,类中的成员都在类的作用域中。在类外定义成员时,要通过 类名::的方式指明类域。

class Date
{
public:

	void Fun1();
private:
	int _year;
	int _month;
	int _day;
};
void Date::Fun1()
{
	//...
}

类的访问限定符

在C++中,用类将对象的属性与方法结合在一块,让对象更加完善。通过访问限定符的控制,可以有选择性的将内部的部分接口提供给外部使用。这也体现了封装的特性。

访问限定符介绍

1.public修饰的成员在类外可以直接被访问

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

3.访问限定符的作用域是从该访问限定符出现的位置直到下一个访问限定符出现为止。

4.如果当前访问限定符的后面不在有其它访问限定符,作用域直到类结束。

5.class的默认访问权限为private,struct的默认访问权限是public。

封装

封装本质上是一种管理,让用户更方便使用类。将数据和操作数据的方法结合在一起,隐藏对象的属性和实现细节,仅对外提供接口来和对象进行交互。

 对于汽车这样的复杂的对象来说,提供给用户的接口只有方向盘、离合、刹车、油门等,让驾驶员和汽车进行交互,完成驾驶任务。但实际上汽车内部真正工作的却是发动机,驱动电机等等被封装起来的内部核心部件。在C++中实现封装,将数据和方法封装起来,通过访问权限来隐藏对象内部的实现细节,控制那些方法可以在类外部直接被使用。

封装的意义

在C语言中定义的结构体中,成员变量都是暴露出来的,在外部可以任意访问,方法暴露在外部。

struct Date
{
	int _year = 2001;
	int _month = 10;
	int _day = 1;
};

void _Show(Date* date)
{
	printf("%d年%d月%d日\n", date->_year, date->_month, date->_day);
}

int main()
{
	Date da1;
	da1._day = 35;
	_Show(&da1);
	return 0;
}

结构体中的成员可以随意的访问,这就存在着一些风险。封装的价值就是将上述的成员和函数围在一个“墙”中,只把部分接口暴露出来。

class Date
{
public:
	void init(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void _Show()
	{
		printf("%d年%d月%d日\n", _year, _month, _day);
	}
private:
	int _year = 2001;
	int _month = 10;
	int _day = 1;
};



int main()
{
	Date da1;
	da1.init(2001,10,3);
	da1._Show();
	return 0;
}

类的实例化

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

2.类是对对象进行描述的,类似于建筑图纸,并没有分配实际的空间。

class Date
{
public:
	void _Show()
	{
		printf("%d年%d月%d日\n", _year, _month, _day);
	}

	int _year = 2001;
	int _month = 10;
	int _day = 1;
};

int main()
{
	Date::_year = 1;
	Date::_Show();
	return 0;
}

在上述代码中,即使将类成员变量和属性设置为共有,通过类域仍然是无法访问和调用函数的,因为上述定义的类,就好像是房子的建造图纸,并没有实际的空间,你无法在图纸中进行午睡!

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

class Date
{
public:
	void init(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void _Show()
	{
		printf("%d年%d月%d日\n", _year, _month, _day);
	}

	int _year = 2001;
	int _month = 10;
	int _day = 1;
};

int main()
{
	Date d1;
	d1.init(2001, 10, 24);
	d1._Show();
	
	Date d2;
	d2.init(2020, 5, 7);
	d2._Show();
	return 0;
}

 类对象模型

类对象的存储方式

每个对象中的变量是不同,就像下图中的对象属性,每个对象都有各自的姓名,性别和学号,但是调用的函数是同一份,所以类对象的存储方式采用下图的结构,每个对象都有独自的成员变量,但是共享一份函数,这样一来就节省了空间。

如上图所示,只保存成员变量,成员函数存在公共的代码段。

结构体对齐

1. 第一个成员在与结构体偏移量为0的地址处。

2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。注意:对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。VS中默认的对齐数为8

3. 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。

4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

5.修改默认对齐数用#pragma(x),#pragma()恢复默认对齐数。

计算类对象的大小

类对象大小的计算,只考虑成员变量,不考虑函数。计算规则和计算结构体的规则一致,要考虑内存对齐。

class A
{
private:
	int _a;
	char _ch;
	int _b;
};

int main()
{
	int ret = sizeof(A);
	cout << ret << endl;
	return 0;
}

 

需要注意的是,当计算的是一个空类时,空类的大小是1,编译器给了空类一个字节来标识这个类的对象。

    class Date
	{
        void init(int year, int month, int day)
		{
			//...
		}
	};
	
	
	int main()
	{
		int ret = sizeof(Date);
		cout << ret << endl;
		return 0;
	}

this指针

1.this指针的类型是 类类型 *const,在成员函数中不能改变this指针的指向。

2.this指针只在“成员函数的内部使用”。

3.this指针本质上是“成员函数”的形参,当类对象调用成员函数时,将对象地址作为实参传递给形参(类类型* const ),所以this指针是存储在栈帧中的

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

5.this指针可以为空,可以访问成员函数,成员函数是在公共代码区的,但是如果访问了成员变量就会运行崩溃。

当this指针为nullptr时,如果只访问了成员函数,是不会报错的。

class Date
{
public:
	void Fun1()
	{
		cout << "函数调用" << endl;
	}
private:
	int _year = 2001;
	int _month = 10;
	int _day = 1;
};

int main()
{
	Date* da = nullptr;
	da->Fun1();
	return 0;
}

this指针为空且访问了成员变量,程序就会崩溃。

class Date
{
public:
	void Fun1()
	{
		cout << _year<< _month<<_day<<endl;
	}
private:
	int _year = 2001;
	int _month = 10;
	int _day = 1;
};

int main()
{
	Date* da = nullptr;
	da->Fun1();
	return 0;
}

 问题解答

1.this指针是作为参数传递的,存在栈帧中。this指针是“成员函数”第一个隐含的指针形参,一般由编译器通过ecx寄存器自动传递,不需要用户显示传递。

2.this指针可以为空,可以调用成员函数,但是如果涉及到成员变量,就会崩溃,因为发生了空指针的解引用。

3.类中包含成员变量和成员函数,通过访问限定符的控制有选择性的向外部提供接口。

4.类的大小计算只关注成员变量即可,计算规则和遵循内存对齐的规则。

5.空的大小为1,编译器给了空类一个字节来标识这个类的对象存在。

6.封装的本质是一种管理,让用户更方便使用类。将数据和操作数据的方法结合在一起,隐藏对象的属性和实现细节,仅对外提供接口来和对象进行交互。

7.C++需要兼容C语言,在C++中struct仍然可以当结构体使用。struct和class都可以用来定义类,struct定义的类默认权限是public的,class定义的类默认权限是private的。

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

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

相关文章

数青蛙​、[USACO10FEB]Chocolate Giving S

一、1419. 数青蛙 思路 这道题有俩种解法&#xff0c;一是记数&#xff0c;二是贪心 记数&#xff1a; 这是官方的题解 我们用frog_ num来表示现在正在发出蛙鸣声的青蛙数目&#xff0c;用cnt[c] 示已经发出-次有效蛙鸣中的字符c的青蛙个数,比如当cnt[c] 2时表示当前有2只…

[mini LCTF 2023] 西电的部分

感觉比赛还是很不错&#xff0c;就是有点难了&#xff0c;不过都是简单题重复更没意思。作出一道来就有一点收获。 misc1 签到题也不简单&#xff0c;已经很久不作misc了&#xff0c;感觉这东西需要安的东西太多&#xff0c;怕机子累坏了。 一个复合的wav声音文件&#xff0…

【Android入门到项目实战-- 8.5】—— 使用HTTP协议访问网络的实践用法

目录 准备工作 一、创建HttpUtil类 二、调用使用 一个应用程序可能多次使用到网络功能&#xff0c;这样就会大量代码重复&#xff0c;通常情况下我们应该将这些通用的网络操作封装到一个类里&#xff0c;并提供一个静态方法&#xff0c;想要发送网络请求的时候&#xff0c;只…

【c语言】字符串匹配(搜索) | API仿真

c语言系列专栏&#xff1a;c语言之路重点知识整合 字符串知识点&#xff1a;字符串基本概念、存储原理 字符串匹配 目录 一、字符串匹配二、strstr仿真声明&#xff1a;指针方式定义&#xff1a;调用测试&#xff1a;运行结果&#xff1a; 一、字符串匹配 字符串匹配是对一个…

HttpClient连接池使用不当问题分析解决

目录 背景代码实现工具类功能实现模拟使用 问题分析与定位解决方案总结 背景 最近遇到一个HttpClient问题&#xff0c;某个接口一直报404错误。该接口使用HttpClient调用其他服务获取数据&#xff0c;为了提高接口调用性能&#xff0c;利用httpclient池化技术来保证请求的数量…

嵌入式中利用软件实现定时器的两种方法分析

目录 第一&#xff1a;简介 第二&#xff1a;链表实现方式 第三&#xff1a;结构体实现方式 第一&#xff1a;简介 在一般的嵌入式产品设计中&#xff0c;介于成本、功耗等&#xff0c;所选型的MCU基本都是资源受限的&#xff0c;而里面的定时器的数量更是有限。在我们软件…

Origin如何绘制基础图形?

文章目录 0.引言1.绘图操作2.图形设置3.图形标注 0.引言 因科研等多场景需要绘制专业的图表&#xff0c;笔者对Origin进行了学习&#xff0c;本文通过《Origin 2022科学绘图与数据》及其配套素材结合网上相关资料进行学习笔记总结&#xff0c;本文对绘制基础图形进行阐述。 1.…

2023.5.7 第五十二次周报

目录 前言 文献阅读&#xff1a;基于BO-EMD-LSTM模型预测教室长期二氧化碳浓度 背景 思路 BO-EMD-LSTM 混合模型 EMD 算法 与其他模型的比较 结论 论文代码 总结 前言 This week, I studied an article that uses LSTM to predict gas concentration.This study wa…

Springboot +Flowable,按角色分配任务

一.简介 在为 UserTask 设置处理人的时候&#xff0c;除了设置单个的处理人&#xff0c;也可以设置 Group&#xff08;分组&#xff09;&#xff0c;就是某一个用户组内的所有用户都可以处理该 Task。 二.绘制流程图 首先我们还是使用之前旧的流程图&#xff0c;流程图截图如…

从0学Spring Boot框架(Spring Boot配置文件与Spring Boot日志文件)

文章目录 1. 什么是Spring Boot&#xff1f;2. 如何创建Spring Boot项目&#xff1f;3. 验证Spring Boot项目的创建3.1 补充添加依赖3.2 代码示例 4. Spring Boot配置文件4.1 配置文件的作用4.2 配置文件的格式4.2.1 properties的语法4.2.2 yml的语法4.2.3 properties与yml的对…

想把PDF转成Word?这三个免费在线工具不容错过!

在日常工作和学习中&#xff0c;我们经常会遇到需要将PDF文件转为Word文档的情况。本文将介绍三种不同的PDF转Word的方法。 首先是推荐的PDF转Word网站&#xff1a;记灵在线工具&#xff08;http://remeins.com)。 这是一个功能非常强大的PDF在线处理网站&#xff0c;可以完全…

CNI_02_Flannel 跨主机通信Overlay Network三种实现

文章目录 一、前言二、跨主机网络三、UDP模式四、VXLAN模式4.1 VXLAN完全在内核态中构建Overlay Netwok覆盖网络4.2 VXLAN模式整个流程步骤1&#xff1a;网络请求从容器到宿主机步骤2&#xff1a;根据目的容器IP在Node1宿主机上找到正确的route路由步骤3&#xff1a;构建内部数…

深度学习实战项目(一)-基于cnn和opencv的车牌号识别

深度学习实战项目(一)-基于cnn和opencv的车牌号识别 网上大部分是关于tensorflow&#xff0c;使用pytorch的比较少&#xff0c;本文也在之前大佬写的代码的基础上&#xff0c;进行了数据集的完善&#xff0c;和代码的优化&#xff0c;效果可比之前好一点。 数据集 数据集来自…

AutoCV:Python基础总结

目录 Python基础总结前言Python基础课程总结第一课&#xff1a;开发环境和基本数据类型第二课&#xff1a;控制流程和函数第三课&#xff1a;闭包和根号2的求解第四课&#xff1a;类和三大神器第五课&#xff1a;文件IO和pickle、json第六课&#xff1a;作用域、模块和包、Data…

IDM下载器|Windows系统经典下载工具idm6.41|IDM如何在线视频下载工具 |下载视频教程

IDM全称Internet Download Manager,是一种将下载速度提高最多5倍的专业下载工具,支持大部分文件格式下载和基本所有的下载链接,无视网址本身下载限速,直接达到电脑该有的网速。 下载更快更可靠 下载INTERNET DOWNLOAD MANAGER(IDM下载器)开始您的极速下载旅程&#xff0c;永远…

鲲志说 我的创作纪念日(2023-05-07)

目录 前言有时候缘分就是这么巧&#xff01;努力终会有所获日常规划成就憧憬 前言 今天是个特殊的日子&#xff0c;是我成为创作者的第2048天。但不仅仅是因此今天才特殊&#xff0c;更重要的是因为你&#xff0c;今天才特殊&#xff0c;值得纪念。不管前路如何&#xff0c;积…

微信小程序开发19__第三方UI组件Vant Weapp的应用

为了提高小程序的开发效率&#xff0c; 可以考虑使用第三方 UI 组件来实现界面的视觉统一。 本文以有赞第三方 UI 组件库 Vant Weapp 为例&#xff0c;介绍如何使用自定义组件 实现一个小程序。 Vant Weapp 是一款轻量、 可靠的小程序UI组件库&#xff0c; 与有赞移动端组…

数字图像处理-绪论

数字图像处理-绪论 文章目录 前言一、闲谈二、什么是数字图像处理&#xff1f;2.1. 什么是数字图像&#xff1f;2.1.1. 可见光图像2.1.2. 不可见光图像 2.2. 什么是数字图像处理&#xff1f; 三、数字图像处理的前世今生3.1. 数字图像处理的前世3.2. 数字图像处理的今生 四、数…

计网笔记 01 概述 计算机网络体系结构、参考模型

文章目录 前言1、计网概述1.1 概念、组成、功能、分类1.1.1 概念1.1.2 计网组成1.1.2 计网分类 1.2 标准化工作及相关组织1.2.1 标准的分类 1.3 性能指标★★★1.3.1 速率相关性能指标1.3.2 时延相关指标 2、体系结构&参考模型★★★★★&#xff08;对应王道视频7-10p 相当…

【MySQL学习】MySQL 内置函数

文章目录 一、日期函数二、字符串函数三、数学函数四、其他函数 一、日期函数 函数名称功能描述current_data()获取当前日期current_time()获取当前时间current_timestamp()获取当前时间戳date()返回datetime的日期部分date_add(date, interval d_value_type)以date为基础&…