当前位置: 首页 > news >正文

(学习总结10)C++类和对象1

C++类和对象1

  • 一、类的定义
    • 1.类定义格式
    • 2.访问限定符
    • 3. 类域
  • 二、实例化
    • 1.实例化概念
    • 2.对象大小
  • 三、this指针
  • 四、C++和C语言实现Stack对比

以下代码环境在 VS2022

一、类的定义

1.类定义格式

  1. class 为定义类的关键字,Stack 为类的名字, { } 中为类的主体,注意类定义结束时后面分号不能省略。类体中内容称为类的成员,类中的变量称为类的属性或成员变量,类中的函数称为类的方法或者成员函数

  2. 为了区分成员变量,一般习惯上成员变量会加一个特殊标识,如成员变量前面或者后面加 “ _ ” 或者 “ m ” 开头,注意C++中这个并不是强制的,只是一些惯例。

  3. C++中 struct 也可以定义类,C++兼容C中 struct 的用法,同时 struct 升级成了类,明显的变化是 struct 中可以定义函数,一般情况下我们还是推荐用 class 定义类

  4. 定义在类里面的成员函数默认加上 inline

#include <iostream>class Stack
{
public:// 成员函数void init(int n = 4){_arr = nullptr;_capacity = _size = 0;checkCapacity();}int top(){return _arr[_size - 1];}void pop(){--_size;}void push(int x){checkCapacity();_arr[_size++] = x;}void destroy(){free(_arr);_arr = nullptr;_capacity = _size = 0;}void checkCapacity(){if (_capacity <= _size){int newCapacity = _capacity == 0 ? 4 : _capacity * 2;int* temp = (int*)realloc(_arr, sizeof(int) * newCapacity);if (temp == nullptr){perror("realloc faild");return;}_arr = temp;_capacity = newCapacity;}}private:// 成员变量int* _arr;int _capacity;int _size;};int main()
{Stack st;st.init();st.push(1);st.push(2);st.push(3);st.destroy();return 0;
}

2.访问限定符

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

  2. public 修饰的成员在类外可以直接被访问,protected 和 private 修饰的成员在类外不能直接被访问,protected 和 private 在这方面的作用是一样的。(在继承中才可体现他们的区别

  3. 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止,如果后面没有访问限定符,作用域就到 “ } ” 即类结束。

  4. class 定义成员没有被访问限定符修饰时默认为 private,struct 默认为 public

  5. 一般成员变量都会被限制为 private / protected,需要给别人使用的成员函数会修饰为 public。

class Student
{// 访问限定符public:protected:private:};

3. 类域

  1. 类定义了一个新的作用域,类的所有成员都在类的作用域中,在类体外定义成员时,需要使用 “ :: ” 作用域操作符指明成员属于哪个类域。
  2. 类域影响的是编译的查找规则,下面程序中 init 如果不指定类域 Stack,那么编译器就把 init 当成全局函数,那么编译时,找不到 _arr 等成员的声明 / 定义在哪里,就会报错。指定类域 Stack,就是知道 init 是成员函数,当前域找不到的 _arr 等成员,就会到类域中去查找。
class Stack
{
public:void init(int x);private:int* _arr;int _capacity;int _size;};// 声明和定义分离
void Stack::init(int x)
{//...
}

二、实例化

1.实例化概念

  1. 用类类型在物理内存中创建对象的过程,称为类实例化出对象。
  2. 类是对象进行一种抽象描述,是一个模型一样的东西,限定了类有哪些成员变量,这些成员变量只是声明,没有分配空间,用类实例化出对象时,才会分配空间
  3. 一个类可以实例化出多个对象,实例化出的对象占用实际的物理空间,存储类成员变量。打个比方:类实例化出对象就像现实中使用建筑设计图建造出房子,类就像是设计图,设计图规划了有多少个房间,房间大小功能等,但是并没有实体的建筑存在,也不能住人,用设计图修建出房子,房子才能住人。同样类就像设计图一样,不能存储数据,实例化出的对象才能分配物理内存存储数据。

2.对象大小

类实例化出的每个对象,都有独立的数据空间,所以对象中肯定包含成员变量。但成员函数不一样,首先函数被编译后是一段指令,对象中没办法存储,这些指令存储在一个单独的区域(代码段),那么对象中非要存储的话,只能是成员函数的指针。并且对象中也没有存储其指针的必要,Date 实例化 d1 和 d2 两个对象,d1 和 d2 都有各自独立的成员变量 _year / _month / _day 存储各自的数据,但是 d1 和 d2 的成员函数 init / print 指针却是一样的,存储在对象中就浪费了。如果用 Date 实例化 100 个对象,那么成员函数指针就重复存储 100 次,太浪费了。

#include <iostream>
using namespace std;class Date
{public:void init(int year = 2000, int month = 1, int day = 1){_year = year;_month = month;_day = day;}void print(){cout << _year << "/" << _month << "/" << _day << endl;;}private:// 只是声明,没有开空间int _year;int _month;int _day;};int main()
{Date d1;Date d2;d1.init(2024, 8, 2);d1.print();d2.init(2014, 8, 2);d2.print();return 0;
}

上面我们分析了对象中只存储成员变量,C++规定类实例化的对象也要符合内存对齐的规则

内存对齐规则:

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

博客 (学习总结6)C语言结构体的内存对齐和位段实现 对内存对齐有详细的解释,这里不赘述。

没有成员变量的类为表示对象存在,给定 1 字节,纯粹为了占位标识对象存在

#include <iostream>
using namespace std;class Student
{;
};int main()
{Student a;// 大小都为 1 字节cout << sizeof(a) << endl;cout << sizeof(Student) << endl;return 0;
}

三、this指针

  1. Date 类中有 init 与 print 两个成员函数,函数体中没有关于不同对象的区分,那当 d1 调用 init 和 print 函数时,为分辨应该访问的是 d1 对象还是 d2 对象,C++给了一个隐含的 this指针 解决这个问题。

  2. 编译器编译后,类的成员函数默认都会在形参第一个位置,增加一个当前类类型的指针,叫做 this指针。比如 Date 类的 init 的真实原型为,void init(Date* const this, int year, int month, int day)

  3. 类的成员函数中访问成员变量,本质都是通过 this指针 访问的,如 init 函数中给 _year 赋值,可改为 this->_year = year。

  4. C++规定不能在实参和形参的位置显示的写 this 指针(编译时编译器会处理),但是可以在函数体内显示使用 this 指针

  5. this指针 存放在寄存器中。

class Date
{public://void init(Date* const this, int year = 2000, ...)void init(int year = 2000, int month = 1, int day = 1){// 不能修改//this = nullptr;//_year = year;//_month = month;//_day = day;this->_year = year;this->_month = month;this->_day = day;}void print(){cout << _year << "/" << _month << "/" << _day << endl;;}private:int _year;int _month;int _day;};

四、C++和C语言实现Stack对比

面向对象三大特性:封装、继承、多态,下面的对比可以初步体现封装。
通过下面两份代码对比,我们发现C++实现 Stack 形态上还是发生了挺多的变化,底层和逻辑上没啥变化。

C语言版本 Stack,详细可参考博客 栈的讲解与实现

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>#define INIT_CAPACITY 4#define EXPANSION_MULTIPLE 2typedef int STDataType;typedef struct Stack
{STDataType* arr;int size;int capacity;
} Stack, * pStack;bool StackEmpty(pStack pst)
{assert(pst);return pst->size == 0;
}void StackInit(pStack pst)
{assert(pst);pst->arr = NULL;pst->size = 0;pst->capacity = 0;
}void StackDestroy(pStack pst)
{assert(pst);free(pst->arr);pst->size = 0;pst->capacity = 0;
}void StackPush(pStack pst, STDataType x)
{assert(pst);if (pst->size == pst->capacity){int newCapacity = pst->capacity == 0 ? INIT_CAPACITY : pst->capacity * EXPANSION_MULTIPLE;STDataType* temp = (STDataType*)realloc(pst->arr, newCapacity * sizeof(STDataType));if (temp == NULL){perror("realloc failed");return;}pst->arr = temp;pst->capacity = newCapacity;}pst->arr[pst->size++] = x;
}void StackPop(pStack pst)
{assert(pst);assert(!StackEmpty(pst));--pst->size;
}STDataType StackTop(pStack pst)
{assert(pst);assert(!StackEmpty(pst));return pst->arr[pst->size - 1];
}int StackSize(pStack pst)
{assert(pst);return pst->size;
}

C++版本 Stack:

#include <iostream>
#include <assert.h>
using namespace std;const int INIT_CAPACITY = 4;const int EXPANSION_MULTIPLE = 2;typedef int STDataType;class Stack
{
public:bool empty();void init();void destroy();void push(STDataType x);void pop();STDataType top();int size();private:STDataType* _arr;int _size;int _capacity;};bool Stack::empty()
{return _size == 0;
}void Stack::init()
{_arr = nullptr;_size = _capacity = 0;
}void Stack::destroy()
{free(_arr);_arr = nullptr;_size = _capacity = 0;
}void Stack::push(STDataType x)
{if (_size == _capacity){int newCapacity = _capacity == 0 ? INIT_CAPACITY : _capacity * EXPANSION_MULTIPLE;STDataType* temp = (STDataType*)realloc(_arr, newCapacity * sizeof(STDataType));if (temp == nullptr){perror("realloc failed");return;}_arr = temp;_capacity = newCapacity;}_arr[_size++] = x;
}void Stack::pop()
{assert(!empty());--_size;
}STDataType Stack::top()
{assert(!empty());return _arr[_size - 1];
}int Stack::size()
{return _size;
}int main()
{Stack a;a.init();a.push(1);a.push(2);a.push(3);a.push(4);while (!a.empty()){cout << a.top() << endl;a.pop();}a.destroy();return 0;
}
  1. C++中数据都放到了类里面,通过访问限定符进行了限制,不能再随意通过对象直接修改数据,这是C++封装的一种体现,这个是最重要的变化。这里的封装的本质是一种更严格规范的管理,避免出现乱访问修改的问题。当然封装不仅仅是这样的,这里就不展开讲了。
  2. C++中有一些相对方便的语法,比如缺省参数,成员函数每次不需要传对象地址,因为 this 指针隐含的传递了,方便了很多,使用类型不再需要 typedef 类名就很方便。

相关文章:

(学习总结10)C++类和对象1

C类和对象1 一、类的定义1.类定义格式2.访问限定符3. 类域 二、实例化1.实例化概念2.对象大小 三、this指针四、C和C语言实现Stack对比 以下代码环境在 VS2022。 一、类的定义 1.类定义格式 class 为定义类的关键字&#xff0c;Stack 为类的名字&#xff0c; { } 中为类的主体…...

进击大数据系列(一):Hadoop 基本概念与生态介绍

进击大数据系列&#xff08;一&#xff09;&#xff1a;Hadoop 基本概念与生态介绍-腾讯云开发者社区-腾讯云 Hadoop 简介-CSDN博客 hadoop-common-3.2.1.jar hadoop-mapreduce-client-core-3.2.1.jar hadoop-hdfs-3.2.1.jar hadoop-core 依赖之间关系...

评价类算法--模糊综合评价算法模型

一.概述 二.经典集合和模糊集合的基本概念 经常采用向量表示法来进行表示 三.隶属函数的三种确定方法 其中,梯形分布用得最多 四.应用:模糊综合评价 对应一个指定的评语: 选择一个方案:...

哪些系统需要按照等保2.0进行定级?

等保2.0适用的系统类型 根据等保2.0的要求&#xff0c;需要进行定级的系统主要包括但不限于以下几类&#xff1a; 基础信息网络&#xff1a;包括互联网、内部网络、虚拟专用网络等。云计算平台/系统&#xff1a;涵盖公有云、私有云、混合云等多种部署模式的云服务平台。大数据…...

自注意力和位置编码

一、自注意力 1、给定一个由词元组成的输入序列x1,…,xn&#xff0c; 其中任意xi∈R^d&#xff08;1≤i≤n&#xff09;。 该序列的自注意力输出为一个长度相同的序列 y1,…,yn&#xff0c;其中&#xff1a; 2、自注意力池化层将xi当作key&#xff0c;value&#xff0c;query来…...

“文件夹提示无法访问?高效数据恢复策略全解析“

一、现象解析&#xff1a;文件夹为何提示无法访问&#xff1f; 在日常使用电脑的过程中&#xff0c;不少用户可能会突然遇到文件夹提示“无法访问”的尴尬情况。这一提示不仅阻断了对重要文件的即时访问&#xff0c;还可能预示着数据丢失的风险。造成这一现象的原因多种多样&a…...

结构开发笔记(一):外壳IP防水等级与IP防水铝壳体初步选型

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/140928101 长沙红胖子Qt&#xff08;长沙创微智科&#xff09;博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV…...

WPF Datagrid控件,获取某一个单元格中的控件

在WPF应用程序中&#xff0c;比如需要获取特定 DataGrid 单元格中的 TextBlock 控件&#xff0c;可以通过访问 DataGridRow 和 DataGridCell 对象。以下是一个例子&#xff0c;展示如何获取 DataGrid 的第二行第一列中的 TextBlock 控件&#xff0c;并修改其属性。 1. 在XAML中…...

P10838 『FLA - I』庭中有奇树

前言 本题解较为基础&#xff0c;推导如何得出二分解题思路。 题目大意 给出无根带权树&#xff0c;双方采取最佳策略&#xff0c;求节点S->T的最短路。 有两种操作&#xff1a; 我方至多可以使用一次传送&#xff0c;花费k元从a传送到b&#xff08;ab不能相邻&#xf…...

WebRTC简介

WebRTC简介 WebRTC&#xff08;Web Real-Time Communication&#xff09;是一项开源的实时通信技术&#xff0c;它允许网页浏览器进行实时语音、视频和数据共享通信&#xff0c;而无需安装额外的插件或应用程序。WebRTC的出现极大地简化了实时通信的开发和部署过程&#xff0c…...

一套直播系统带商城源码 附搭建教程

本站没搭建测试过&#xff0c;有兴趣的自己折腾了&#xff0c;内含教程&#xff01; 功能介绍&#xff1a; 礼物系统&#xff1a;普通礼物、豪华礼物、热门礼物、守护礼物、幸运礼物 提现方式&#xff1a;统一平台提现日期及方式&#xff0c;方便用户执行充值提现操作 连麦…...

Netty 总结与补充(十)

简单介绍一下 Netty&#xff1f;你为什么会用到Netty&#xff1f;说说你对Netty的认识&#xff1f;为什么选用Netty来做通信框架&#xff1f; Netty 是一个高性能、异步事件驱动的 NIO 框架&#xff0c;它提供了对 TCP、UDP 和文件传输的支持&#xff0c;作为一个异步 NIO 框架…...

循环实现异步变同步的问题

一、背景 在开发中遇到在循环中调用异步接口的问题&#xff0c;导致页面渲染完成时&#xff0c;没有展示接口返回后拼接的数组数据。二、问题 在代码中使用了map进行循环&#xff0c;导致调用接口的时候处于异步。this.form.list.map(async el>{el.fileList [];if(el.pic…...

测试GPT4o分析巴黎奥运会奖牌数据

使用GPT4o快速调用python代码&#xff0c;生成数据图表 测试GPT4o分析巴黎奥运会奖牌数据 测试GPT4o分析巴黎奥运会奖牌数据 1.首先我们让他给我们生成下当前奥运奖牌数 2.然后我们直接让GPT帮我们运行python代码&#xff0c;并生成奥运会奖牌图表 3.我们还可以让他帮我们…...

TF卡(SD NAND)参考设计和使用提示

目录 电路设计 Layout 设计说明 贴片注意事项 电路设计 1、参考电路&#xff1a; R1~R5 (10K-100 kΩ)是上拉电阻&#xff0c;当SD NAND处于高阻抗模式时&#xff0c;保护CMD和DAT线免受总线浮动。 即使主机使用SD NAND SD模式下的1位模式&#xff0c;主机也应通过上拉电…...

电源芯片负载调整率测试方法、原理以及自动化测试的优势-纳米软件

在芯片设计研发领域&#xff0c;负载调整率作为稳压电源芯片的关键性能指标&#xff0c;直接关系到芯片的稳定性和可靠性&#xff0c;因此其测试和优化显得尤为重要。以下是对负载调整率测试原理、方法以及使用ATECLOUD-IC芯片测试系统优势的进一步阐述&#xff1a; 负载调整率…...

C++威力强大的助手 --- const

Welcome to 9ilks Code World (๑•́ ₃ •̀๑) 个人主页: 9ilk (๑•́ ₃ •̀๑) 文章专栏&#xff1a; C之旅 const是个奇妙且非比寻常的东西&#xff0c;博主从《Effective C》一书中认识到关于const更深层次的理解&#xff0c;写此博客进行巩固。 &#x…...

测试环境搭建整套大数据系统(十八:ubuntu镜像源进行更新)

镜像源更新为清华源 报错显示 解决方案 做好备份 cp /etc/apt/sources.list /etc/apt/sources.list.bak查看配置信息 sudo vim /etc/apt/sources.listsudo sed -i s/cn.archive.ubuntu.com/mirrors.aliyun.com/g /etc/apt/sources.list sudo apt update...

第128天:内网安全-横向移动IPCATSC 命令Impacket 套件CS 插件全自动

环境部署 案例一&#xff1a; 域横向移动-IPC-命令版-at&schtasks 首先是通过外网web访问到win2008&#xff0c;获得了win2008的权限&#xff0c;这一步不做演示 因为里面的主机都不出网&#xff0c;所以只能利用win2008进行正向或者反向连接 信息收集 域内用户信息&…...

记录一次学习过程(msf、cs的使用、横向渗透等等)

目录 用python搭建一个简单的web服务器 代码解释 MSF msfvenom 功能 用途 查看payloads列表 msfconsole 功能 用途 msfvenom和msfconsole配合使用 来个例子 msf会话中用到的一些命令 在windows中net user用法 列出所有用户账户 显示单个用户账户信息 创建用户账…...

椭圆曲线密码学(ECC)

一、ECC算法概述 椭圆曲线密码学&#xff08;Elliptic Curve Cryptography&#xff09;是基于椭圆曲线数学理论的公钥密码系统&#xff0c;由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA&#xff0c;ECC在相同安全强度下密钥更短&#xff08;256位ECC ≈ 3072位RSA…...

FFmpeg 低延迟同屏方案

引言 在实时互动需求激增的当下&#xff0c;无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作&#xff0c;还是游戏直播的画面实时传输&#xff0c;低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架&#xff0c;凭借其灵活的编解码、数据…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享

文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的&#xff0c;根据Excel列的需求预估的工时直接打骨折&#xff0c;不要问我为什么&#xff0c;主要…...

多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验

一、多模态商品数据接口的技术架构 &#xff08;一&#xff09;多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如&#xff0c;当用户上传一张“蓝色连衣裙”的图片时&#xff0c;接口可自动提取图像中的颜色&#xff08;RGB值&…...

在四层代理中还原真实客户端ngx_stream_realip_module

一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡&#xff08;如 HAProxy、AWS NLB、阿里 SLB&#xff09;发起上游连接时&#xff0c;将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后&#xff0c;ngx_stream_realip_module 从中提取原始信息…...

网站指纹识别

网站指纹识别 网站的最基本组成&#xff1a;服务器&#xff08;操作系统&#xff09;、中间件&#xff08;web容器&#xff09;、脚本语言、数据厍 为什么要了解这些&#xff1f;举个例子&#xff1a;发现了一个文件读取漏洞&#xff0c;我们需要读/etc/passwd&#xff0c;如…...

手机平板能效生态设计指令EU 2023/1670标准解读

手机平板能效生态设计指令EU 2023/1670标准解读 以下是针对欧盟《手机和平板电脑生态设计法规》(EU) 2023/1670 的核心解读&#xff0c;综合法规核心要求、最新修正及企业合规要点&#xff1a; 一、法规背景与目标 生效与强制时间 发布于2023年8月31日&#xff08;OJ公报&…...

go 里面的指针

指针 在 Go 中&#xff0c;指针&#xff08;pointer&#xff09;是一个变量的内存地址&#xff0c;就像 C 语言那样&#xff1a; a : 10 p : &a // p 是一个指向 a 的指针 fmt.Println(*p) // 输出 10&#xff0c;通过指针解引用• &a 表示获取变量 a 的地址 p 表示…...

算法—栈系列

一&#xff1a;删除字符串中的所有相邻重复项 class Solution { public:string removeDuplicates(string s) {stack<char> st;for(int i 0; i < s.size(); i){char target s[i];if(!st.empty() && target st.top())st.pop();elsest.push(s[i]);}string ret…...

【java】【服务器】线程上下文丢失 是指什么

目录 ■前言 ■正文开始 线程上下文的核心组成部分 为什么会出现上下文丢失&#xff1f; 直观示例说明 为什么上下文如此重要&#xff1f; 解决上下文丢失的关键 总结 ■如果我想在servlet中使用线程&#xff0c;代码应该如何实现 推荐方案&#xff1a;使用 ManagedE…...