【C++类和对象】类和对象的引入

💞💞 前言

hello hello~ ,这里是大耳朵土土垚~💖💖 ,欢迎大家点赞🥳🥳关注💥💥收藏🌹🌹🌹
在这里插入图片描述

💥个人主页:大耳朵土土垚的博客
💥 所属专栏:C++入门至进阶
这里将会不定期更新有关C++的内容,希望大家多多点赞关注💖💖

目录

  • 💞💞 前言
  • 1.面向过程与面向对象
  • 2.类的引入
  • 3.类的定义
  • 4.类的访问限定符及封装
    • 4.1 访问限定符
    • 4.2封装
  • 5.类的作用域
  • 6.类的实例化
  • 7.类对象模型
    • 7.1类对象的存储方式猜测
    • 7.2 如何计算类对象的大小
  • 8.this指针
    • 8.1 this指针的引出
    • 8.2 this指针的特性
  • 9.结语

1.面向过程与面向对象

  • 面向过程和面向对象是两种不同的编程方式。

  • 面向过程编程是一种以过程为基础的编程方式,它将问题分解为一系列的步骤和操作,通过定义和调用函数来实现程序的功能。面向过程强调程序的执行顺序和各个步骤之间的数据传递。

  • 面向对象编程是以对象为基础的编程方式,它将问题抽象为一组对象,并通过定义对象的属性和方法来描述对象的特征和行为。面向对象强调对象之间的交互和消息传递,通过定义类和创建对象来实现程序的功能。
    例如下图:
    在这里插入图片描述

  • 面向过程和面向对象有各自的优缺点和适用场景。面向过程可以更直观地描述问题的步骤和流程,适用于简单的、线性的问题。而面向对象可以更好地组织和管理复杂的问题,提供了更高的可重用性和扩展性。

  • 面向过程和面向对象在实际编程中常常结合使用。面向对象编程可以将复杂的问题分解为多个简单的模块,每个模块使用面向过程的方式来实现。这种结合使用的方式称为面向对象程序设计(OOP)。

2.类的引入

C语言结构体中只能定义变量,在C++中,结构体内不仅可以定义变量,也可以定义函数。比如:之前在数据结构专栏中,用C语言方式实现的栈,结构体中只能定义变量;现在以C++方式实现,会发现struct中也可以定义函数:

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

结果如下:
在这里插入图片描述

上面结构体的定义C++更喜欢用class来代替struct

3.类的定义

class className
{
// 类体:由成员函数和成员变量组成
//...
};  // 一定要注意后面的分号
  • class为定义类的关键字,ClassName为类的名字,{}中为类的主体,注意类定义结束时后面分号不能省略。
  • 类体中内容称为类的成员:类中的变量称为类的属性或成员变量; 类中的函数称为类的方法或者成员函数。
  • 类的两种定义方式:
  1. 声明和定义全部放在类体中,需注意:成员函数如果在类中定义,编译器可能会将其当成内联函数处理。
    例如:
    在这里插入图片描述
  2. 类声明放在.h文件中,成员函数定义放在.cpp文件中,注意:成员函数名前需要加类名::
    例如:
    在这里插入图片描述
    一般情况下,更期望采用第二种方式。
  • 成员变量命名规则的建议:
// 我们看看这个函数,是不是很僵硬?
class Date
{
public:void Init(int year){// 这里的year到底是成员变量,还是函数形参?year = year;}
private:int year;
};
// 所以一般都建议这样
class Date
{
public:void Init(int year){_year = year;}
private:int _year;
};
// 或者这样
class Date
{
public:void Init(int year){mYear = year;}
private:int mYear;
};
// 其他方式也可以的,主要看公司要求。一般都一般都是加个前缀或者后缀标识区分就行

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

4.1 访问限定符

C++实现封装的方式:用类将对象的属性与方法结合在一块,让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用
在这里插入图片描述
【访问限定符说明】

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

4.2封装

  • 面向对象的三大特性:封装、继承、多态。
  • 在类和对象阶段,主要是研究类的封装特性,那什么是封装呢?
  • 封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。
    封装本质上是一种管理,让用户更方便使用类。比如:对于电脑这样一个复杂的设备,提供给用户的就只有开关机键、通过键盘输入,显示器,USB插孔等,让用户和计算机进行交互,完成日常事务。但实际上电脑真正工作的却是CPU、显卡、内存等一些硬件元件。 对于计算机使用者而言,不用关心内部核心部件,比如主板上线路是如何布局的,CPU内部是如何设计的等,用户只需要知道,怎么开机、怎么通过键盘和鼠标与计算机进行交互即可。因此计算机厂商在出厂时,在外部套上壳子,将内部实现细节隐藏起来,仅仅对外提供开关机、鼠标以及键盘插孔等,让用户可以与计算机进行交互即可。
  • 在C++语言中实现封装,可以通过类将数据以及操作数据的方法进行有机结合,通过访问权限来隐藏对象内部实现细节,控制哪些方法可以在类外部直接被使用。

5.类的作用域

类定义了一个新的作用域,类的所有成员都在类的作用域中。在类体外定义成员时,需要使用 :: 作用域操作符指明成员属于哪个类域。
例如:

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

6.类的实例化

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

  1. 类是对对象进行描述的,是一个模型一样的东西,限定了类有哪些成员,定义出一个类并没有分配实际的内存空间来存储它;
    比如:入学时填写的学生信息表,表格就可以看成是一个类,来描述具体学生信息。
    类就像谜语一样,对谜底来进行描述,谜底就是谜语的一个实例。

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

例如:

int main()
{Person._age = 100;   // 编译失败:error C2059: 语法错误:“.”return 0;
}//需要先进行类的实例化

Person类是没有空间的,只有Person类实例化出的对象才有具体的年龄。

  1. 做个比方:类实例化出对象就像现实中使用建筑设计图建造出房子,类就像是设计图,只设计出需要什么东西,但是并没有实体的建筑存在,同样类也只是一个设计,实例化出的对象才能实际存储数据,占用物理空间:
    在这里插入图片描述
    在这里插入图片描述

只有如上图所示利用Person这个类定义出了man这个实例才可以进行后续的一系列操作 ;

7.类对象模型

7.1类对象的存储方式猜测

  • 对象中包含类的各个成员
    在这里插入图片描述

缺陷:每个对象中成员变量是不同的,但是调用同一份函数,如果按照此种方式存储,当一个类创建多个对象时,每个对象中都会保存一份函数代码,相同代码保存多次,浪费空间。那么如何解决呢?

  • 函数代码只保存一份,在对象中保存存放代码的地址
    在这里插入图片描述

  • 只保存成员变量,成员函数存放在公共的代码段
    在这里插入图片描述

    在这里插入图片描述

对于上述三种存储方式,那计算机到底是按照那种方式来存储的?

我们可以通过下面的代码结果来分析:

// 类中既有成员变量,又有成员函数
class A1 {
public:void f1() {}
private:int _a;
};// 类中仅有成员函数
class A2 {
public:void f2() {}
};// 类中什么都没有---空类
class A3
{};int main()
{cout << sizeof(A1) << endl;cout << sizeof(A2) << endl;cout << sizeof(A3) << endl;return 0;
}

结果如下:
在这里插入图片描述
结论

  • 类对象是按照第三种将函数代码放在公共代码区的方式来存储的
  • 一个类的大小,实际就是该类中”成员变量”之和(不包含成员函数),当然要注意内存对齐规则(内存对齐参考结构体内存对齐——C语言结构体内存对齐规则及大小计算)
  • 注意空类的大小,空类比较特殊,编译器给了空类一个字节来唯一标识这个类的对象

7.2 如何计算类对象的大小

例如下面的类:

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

该结构体成员变量只有char类型的变量_a,大小是1字节,再根据内存对齐规则得出该类的大小是1
结果如下:
在这里插入图片描述

8.this指针

8.1 this指针的引出

我们先来定义一个日期类 Date

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 d1, d2;d1.Init(2022, 1, 11);d2.Init(2022, 1, 12);d1.Print();d2.Print();return 0;
}

结果如下:
在这里插入图片描述
对于上述类,有这样的一个问题:

  • Date类中有 Init 与 Print 两个成员函数,函数体中没有关于不同对象的区分,那当d1调用 Init 函数时,该函数是如何知道应该设置d1对象,而不是设置d2对象呢?

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

  • 也就是说在调用成员函数时实际上多传递了一个this参数来定位是哪个类对象,所以对于成员函数你也可以这样写:

class Date
{
public:void Init(int year, int month, int day){this->_year = year;this->_month = month;this->_day = day;}void Print(){cout << this->_year << "-" << this->_month << "-" << this->_day << endl;}
private:int _year;    // 年int _month;  // 月int _day;   // 日
};

结果还是一样的:
在这里插入图片描述

8.2 this指针的特性

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

9.结语

C++中通过类可以将数据以及操作数据的方法进行完美结合,通过访问权限可以控制哪些方法在类外可以被调用,即封装,在使用时就像使用自己的成员一样,更符合人类对一件事物的认知。以上就是C++类和对象上篇的所有内容啦~ 完结撒花 ~🥳🎉🎉

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

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

相关文章

mysql查找binlog的删除记录时间

需求&#xff1a;数据库某表的数据没有了&#xff1b;如何找是什么时修改清掉的&#xff1b; 思路&#xff1a; 1. 查代码&#xff0c;找某表的删除接口&#xff0c;分析是在哪里调用&#xff1b;【部分服务log不全】 2. 查服务的log&#xff1b;【部分服务log不全】 3. 查…

【学习笔记十七】波次管理、自动波次和WOCR介绍及配置

一、手工维护波次 波次是控制仓库活动(如拣配)的仓库请求项目(通常是出库交货订单项目)的分组。这些分组随后在后续流程中一起处理,例如,将分配到波次的所有仓库请求项目传输到仓库任务创建。 注意:仓库请求是出库交货订单、过账更改、库存转储(用于仓库中的内部移动)或入库…

38条Web测试经验分享

1. 页面链接检查 每一个链接是否都有对应的页面&#xff0c;并且页面之间切换正确。可以使用一些工具&#xff0c;如LinkBotPro、File-AIDCS、HTML Link Validater、Xenu等工具。 LinkBotPro不支持中文&#xff0c;中文字符显示为乱码&#xff1b;HTML Link Validater只能测试…

VSCode+Cmake 调试时向目标传递参数

我有一个遍历文件层次结构的程序&#xff0c;程序根据传入的文件路径&#xff0c;对该路径下的所有文件进行遍历。这个程序生成一个名为 ftw 的可执行文件&#xff0c;如果我要遍历 /bin 目录&#xff0c;用法为&#xff1a; ftw /bin问题是&#xff0c;如果我想单步跟踪&…

HBase2.x学习笔记

文章目录 一、HBase 简介1、HBase 定义1.1 概述1.2 HBase 与 Hadoop 的关系1.3 RDBMS 与 HBase 的对比1.4 HBase 特征简要 2、HBase 数据模型2.1 HBase 逻辑结构2.2 HBase 物理存储结构2.3 HBase的表数据模型 3、HBase 基本架构3.1 Master3.2 Region Server3.3 Zookeeper3.4 HD…

每日一练 | 华为认证真题练习Day215

1、下面是一段MUX VLAN中,关于主VLAN和从VLAN的配置,关于此配置说法正确是(多选) A. VLAN 10为主机VLAN B. VLAN 11为主机VLAN C. VLAN12为隔离型从VLAN D. VLAN 11和VLAN 12都为从VLAN E. VLAN 10和VLAN 11都为MUX VLAN 2、BGP邻居建立过程的状态存在以下几种,那么建立一个…

202305青少年软件编程(scratch图形化)等级考试试卷(四级)

第1题&#xff1a;【 单选题】 下列积木运行后的结果是&#xff1f; &#xff08; &#xff09; &#xff08;说明&#xff1a; 逗号后面无空格&#xff09; A:我 B:爱 C:中 D:国 【正确答案】: B 【试题解析】 : 两个字符串连接后的第 8 个字符是“爱” 。 第2题&#…

【工具】智慧树自动播放-油猴、篡改猴脚本,自动播放、自动下一节

一、自动播放脚本 编写此脚本的原因是&#xff0c;女朋友单位要求刷*.zhihuishu.com课程&#xff0c;先是想到用python自动化来处理&#xff0c;折腾半天不太好使&#xff1b;后面想到用油猴脚本来处理&#xff0c;安装了很多个现成的脚本&#xff0c;依旧不好使&#xff0c;只…

基于flutter3.x+window_manager+getx桌面端仿macOS系统

flutter3_macui桌面端仿macOS系统实战项目完结啦&#xff01; 原创研发flutter3.19dart3.3window_managergetx等技术构建桌面版macOS系统。支持自定义毛玻璃虚化背景、Dock菜单多级嵌套自由拖拽排序、可拖拽弹窗等功能。 支持macOS和windows11两种风格。 使用技术 编辑器&…

前端三剑客 —— JavaScript (第十一节)

内容回顾&#xff1a; jQuery 操作DOM jQuery 事件处理 Ajax jQuery 特效案例 全选效果 tab切换 下拉菜单 自定义动画 Bootstrap 入门 首先我们可以在bootstrap官网上进行下载。官网地址:https//www.bootcss.com/ 首先在我们的页面中导入bootstrap的样式&#xff0c;我们可…

推荐系统综述

推荐系统研究综述 - 中国知网 传统推荐方法主要分类&#xff1a; 1)基于内容推荐方法 主要依据用户与项目之间的特征信息,用户之间的联系不会影响推荐结果,所以不存在冷启动和稀疏问题,但是基于内容推荐的结果新颖程度低并且面临特征提取的问题。 基于内容的推荐方法的思想非…

03-echarts如何画立体柱状图

echarts如何画立体柱状图 一、创建盒子1、创建盒子2、初始化盒子&#xff08;先绘制一个基本的二维柱状图的样式&#xff09;1、创建一个初始化图表的方法2、在mounted中调用这个方法3、在方法中写options和绘制图形 二、画图前知识1、坐标2、柱状图图解分析 三、构建方法1、创…

GPT提示词分享 —— 解梦

&#x1f449; 对你描述的梦境进行解读。 我希望你能充当一个解梦者。我将给你描述我的梦&#xff0c;而你将根据梦中出现的符号和主题提供解释。不要提供关于梦者的个人意见或假设。只提供基于所给信息的事实性解释。 GPT3.5的回答 GPT3.5 &#x1f447; 感觉有点傻&#xf…

Slf4j+Log4j简单使用

Slf4jLog4j简单使用 文章目录 Slf4jLog4j简单使用一、引入依赖二、配置 log4j2.xml2.1 配置结构2.2 配置文件 三、使用四、使用MDC完成日志ID4.1 程序入口处4.2 配置文件配置打印4.3 多线程日志ID传递配置 五. 官网 一、引入依赖 <dependencies><dependency><g…

大数据建模理论

文章目录 一、数仓概述1、数据仓库概念1.1 概述1.2 数据仓库与数据库的区别1.3 技术选型和架构 2、数仓常见名词2.1 实体2.2 维度2.3 度量2.4 粒度2.5 口径2.6 指标2.7 标签2.8 自然键/持久键/代理键2.9 退化维度2.10 下钻/上卷2.11 数据集市 3、数仓名词之间关系3.1 实体表&am…

Spring 事务失效总结

前言 在使用spring过程中事务是被经常用的&#xff0c;如果不小心或者认识不做&#xff0c;事务可能会失效。下面列举几条 业务代码没有被Spring 容器管理 看下面图片类没有Componet 或者Service 注解。 方法不是public的 Transactional 注解只能用户public上&#xff0c…

李沐41_物体检测和数据集——自学笔记

边缘框 1.一个边缘框可以通过4个数字定义&#xff08;左上xy&#xff0c;右上xy&#xff0c;左下xy&#xff0c;右下xy&#xff09; 2.标注成本高 目标检测数据集 1.每行表示一个物体&#xff08;图片文件名、物体类别、边缘框&#xff09; 2.COCO&#xff1a;80物体、330…

RAG原理详解

什么是RAG 检索增强生成&#xff08;Retrieval Augmented Generation&#xff0c;简称RAG&#xff09;为大型语言模型&#xff08;LLMs&#xff09;提供了从某些数据源检索到的信息&#xff0c;以此作为生成答案的基础。简而言之&#xff0c;RAG是搜索LLM提示的结合&#xff0…

Mac用户必备神器:Default Folder X,让文件操作更快捷、更智能!

Default Folder X for Mac是一款功能强大的文件管理辅助工具&#xff0c;它为Mac用户带来了前所未有的文件操作体验。&#x1f31f; 无论是日常办公、学习还是娱乐&#xff0c;Default Folder X都能帮助你更高效地管理文件&#xff0c;让你的工作更加得心应手。&#x1f4bc; …

AD高速板设计(笔记)

Alt左键高亮某个器件或属性&#xff0c;点击任意位置取消高亮。 TP设置旋转角度为45度&#xff0c;即可选中器件按空格旋转时候每次旋转45度。 先画出想要割槽的区域&#xff0c;选中之后TVB即可开槽。 左右翻转电路板&#xff1a;VB DR打开规则设置 UFO对器件进行扇出&#…