【类和对象】类的作用域 | 类的实例化 | 类对象模型 | this指针

目录

5.类的作用域

6.类的实例化

6.1成员的声明和定义 

6.2实例化出的对象大小

7.类对象模型❗❗

7.1如何计算类对象的大小

7.2类对象的存储方式猜测

7.3结构体内存对齐规则

7.3.1内存对齐

7.3.2大小端  

8.this指针

8.1this指针的引出

8.2this指针的特性

C和C++实现栈的对比


  • 类,对象,成员变量,变量,成员函数的关系

5.类的作用域

类定义了一个新的作用域,类的所有成员都在类的作用域中。

  • 类域能解决一定的命名冲突问题
  • 在类体外定义成员时,需要使用 :: 作用域操作符指明成员属于哪个类域。
//声明.h
class Person
{
public:void PrintPersonInfo();
private:char _name[20];char _gender[3];int  _age;
};//定义.cpp
// 这里需要指定PrintPersonInfo是属于Person这个类域
void Person::PrintPersonInfo()
{cout << _name << " " << _gender << " " << _age << endl;
}

6.类的实例化

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

  • 类是对对象进行描述的,是一个模型一样的东西,限定了类有哪些成员。
  • 定义出一个类并没有分配实际的内存空间来存储它;比如:入学时填写的学生信息表,表格就可以看成是一个类,来描述具体学生信息。
  •  一个类可以实例化出多个对象,实例化出的对象 占用实际的物理空间,存储类成员变量
  • 类是没有空间的,只有类的实例化出的对象才有具体的空间。

举例:

  • 类就像谜语一样,对谜底来进行描述,谜底就是谜语的一个实例。
  • 谜语:"年纪不大,胡子一把,主人来了,就喊妈妈" 谜底:山羊

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

 

6.1成员的声明和定义 

  • 无论是成员变量/成员函数在类中,只要还未被实例化成对象,那么它们都是一种声明,因为它们只是类,并不存在空间。
  • 定义并不是给值,而是为类开辟空间,也就是实例化。
  • 定义的时候可以初始化,但是只初始化并不代表定义。
#include<stdlib.h>
#include<iostream>
using namespace std;
class Date
{
public:void Init(int year, int month, int day){_year = year;_month = month;_day = day;}
private://这里是声明还是定义?声明int _year;int _month;int _day;
};int main()
{Date s;//定义了s.Init(1,1,1);
❌	Date::_year++;//不能因为它只是声明,并没有开辟空间
❌  Date._month = 100;  // 编译失败:error C2059: 语法错误:“.” return 0;
}

6.2实例化出的对象大小

 移步☞类对象的存储方式。

7.类对象模型❗❗

《深度探索C++对象模型》这本书中对对象模型的描述如下:

有两个概念可以解释C++对象模型:

  • 语言中直接支持面向对象程序设计的部分。
  • 对于各种支持的底层实现机制。

对象模型是指在面向对象编程中,为了描述和处理现实世界中的实体、事物或概念所构建的抽象模型。它通常由类、对象、属性、方法等元素组成,用于描述实体之间的关系、结构和行为。


❓❓问题:类中既可以有成员变量,又可以有成员函数,那么一个类的对象中包含了什么?类对象的存储方式?如何计算一个类的大小? 下面我们来一起探讨。

7.1如何计算类对象的大小

  • 类的实例化=对象
  • sizeof(类名)
  • sizeof(对象)
  • 二者计算都是类实例化的大小,也就是类对象的大小。
  • 一个类的大小,实际就是该类中”成员变量”之和,当然要注意内存对齐
  • 注意空类的大小,空类比较特殊,编译器给了空类一个字节来唯一标识这个类的对象
  • 没有成员变量的类对象大小1字节,标识对象实例化,定义出来存在。
class A
{
public:void PrintA(){cout << _a << endl;}
private:int _a;char _i;
};

❓计算下面类对象的大小: sizeof(A1) : ______ sizeof(A2) : ______ sizeof(A3) : ______

#include<stdlib.h>
#include<iostream>
using namespace std;
// 类中既有成员变量,又有成员函数
//内存对齐存储
class A1 {
public:void f1() {}
private:int _a;char _i;
};// 类中仅有成员函数
//标识对象实例化,定义出来存在
class A2 {
public:void f2() {}
};// 类中什么都没有---空类
class A3
{};
int main()
{cout << sizeof(A1) << endl;cout << sizeof(A2) << endl;cout << sizeof(A3) << endl;return 0;
}

7.2类对象的存储方式猜测

类对象的存储方式有两种:

  • 对象中包含类的各个成员(不用)
  • 代码只保存一份,在对象中保存存放代码的地址(以后)
  • 只保存成员变量,成员函数存放在公共的代码段(现阶段)
//现阶段
class Date
{
public:void Init(int year, int month, int day){_year = year;_month = month;_day = day;}int _year;int _month;int _day;
};int main()
{Date d1;Date d2;//不是一块空间,成员变量各自是各自的空间d1._year;d2._month;//是一块空间,成员函数是一块空间d1.Init(1,1,1);d2.Init(1,1,1);return 0;
}

 【对象中包含类的各个成员】

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


 【代码只保存一份,在对象中保存存放代码的地址】


 【只保存成员变量,成员函数存放在公共的代码段】

7.3结构体内存对齐规则

1. 第一个成员在与结构体偏移量为0的地址处。
2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。

  • 注意:对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。
  • VS中默认的对齐数为8。

3. 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。
4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。


【面试题】

  • 1. 结构体怎么对齐? 为什么要进行内存对齐?
  • 2. 如何让结构体按照指定的对齐参数进行对齐?能否按照3、4、5即任意字节对齐?
  • 3. 什么是大小端?如何测试某机器大端还是小端,有没有遇到过要考虑大小端的场景。
  • 前面C语言进阶我们也讲解过(结构体)C语言之自定义类型_结构体篇(1)-CSDN博客

7.3.1内存对齐

  • 怎样内存对齐?
  • 类对象的包含了什么,需要包括成员函数吗?
  • 为什么要内存对齐?
  • 可以改变对齐参数吗?

【怎么内存对齐---按照规则】 

类的对象存储空间只包含了成员变量,成员函数在公共区域。 

#include<iostream>
using namespace std;
struct A
{
private:int _a;char _i;
};struct B
{
private:char _i;int _a;
};

 【为什么要内存对齐】

  • 对齐是为了提高效率!
  • 硬件规定CPU一次只能读取4/8个字节。
  • 32/64个线,32/64个位,组成0/1的二进制数。(消耗相同,一次只读取32/64位,4/8个字节)
  • 硬件规定:CPU的控制器只能从整数倍开始读取。起始位置必须是整数倍的位置。
  • 以上规定从而导致了:对齐和不对齐读取存在效率上的问题。
  • 对齐读取的次数比不对齐读取的次数多。

【对齐可以改变编译器默认对齐数的大小】

#include<iostream>
using namespace std;//改变默认对齐数的大小
#pragma pack(1)//相当于不对齐struct A
{
private:int _a;char _i;
};struct B
{
private:char _i;int _a;
};int main()
{cout << sizeof(A) << endl;cout << sizeof(B) << endl;return 0;
}

7.3.2大小端  

8.this指针

8.1this指针的引出

8.2this指针的特性

C和C++实现栈的对比

【C语言】

可以看到,在用C语言实现时,Stack相关操作函数有以下共性:

  • 每个函数的第一个参数都是Stack*
  • 函数中必须要对第一个参数检测,因为该参数可能会为NULL
  • 函数中都是通过Stack*参数操作栈的
  • 调用时必须传递Stack结构体变量的地址

结构体中只能定义存放数据的结构,操作数据的方法不能放在结构体中,即数据和操作数据方式是分离开,而且实现上相当复杂一点,涉及到大量指针操作,稍不注意可能就会出错。 


【C++】感谢祖师爷

  • C++中通过类可以将数据 以及 操作数据的方法进行完美结合。
  • 通过访问权限可以控制那些方法在类外可以被调用,即封装。
  • 在使用时就像使用自己的成员一样,更符合人类对一件事物的认知。
  • 而且每个方法不需要传递Stack*的参数了。
  • 编译器编译之后该参数会自动还原,即C++中 Stack *参数是编译器维护的,C语言中需用用户自己维护。

【C语言实现】

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>typedef int DataType;
typedef struct Stack
{DataType* array;int capacity;int size;
}Stack;
void StackInit(Stack* ps)
{assert(ps);ps->array = (DataType*)malloc(sizeof(DataType) * 3);if (NULL == ps->array){assert(0);return;}ps->capacity = 3;ps->size = 0;
}
void StackDestroy(Stack* ps)
{assert(ps);if (ps->array){free(ps->array);ps->array = NULL;ps->capacity = 0;ps->size = 0;}
}
void CheckCapacity(Stack* ps)
{if (ps->size == ps->capacity){int newcapacity = ps->capacity * 2;DataType* temp = (DataType*)realloc(ps->array,newcapacity * sizeof(DataType));if (temp == NULL){perror("realloc申请空间失败!!!");return;}ps->array = temp;ps->capacity = newcapacity;}
}
void StackPush(Stack* ps, DataType data)
{assert(ps);CheckCapacity(ps);ps->array[ps->size] = data;ps->size++;
}
int StackEmpty(Stack* ps)
{assert(ps);return 0 == ps->size;
}
void StackPop(Stack* ps)
{if (StackEmpty(ps))return;ps->size--;
}
DataType StackTop(Stack* ps)
{assert(!StackEmpty(ps));return ps->array[ps->size - 1];
}
int StackSize(Stack* ps)
{assert(ps);return ps->size;
}
int main()
{Stack s;StackInit(&s);StackPush(&s, 1);StackPush(&s, 2);StackPush(&s, 3);StackPush(&s, 4);printf("%d\n", StackTop(&s));printf("%d\n", StackSize(&s));StackPop(&s);StackPop(&s);printf("%d\n", StackTop(&s));printf("%d\n", StackSize(&s));StackDestroy(&s);return 0;
}

【C++实现】 

#include<iostream>
using namespace std;typedef int DataType;
class Stack
{
public:void Init(){_array = (DataType*)malloc(sizeof(DataType) * 3);if (NULL == _array){perror("malloc申请空间失败!!!");return;}_capacity = 3;_size = 0;}void Push(DataType data){CheckCapacity();_array[_size] = data;_size++;}void Pop(){if (Empty())return;_size--;}DataType Top() { return _array[_size - 1]; }int Empty() { return 0 == _size; }int Size() { return _size; }void Destroy(){if (_array){free(_array);_array = NULL;_capacity = 0;_size = 0;}}
private:void CheckCapacity(){if (_size == _capacity){int newcapacity = _capacity * 2;DataType* temp = (DataType*)realloc(_array, newcapacity *sizeof(DataType));if (temp == NULL){perror("realloc申请空间失败!!!");return;}_array = temp;_capacity = newcapacity;}}
private:DataType* _array;int _capacity;int _size;
};
int main()
{Stack s;s.Init();s.Push(1);s.Push(2);s.Push(3);s.Push(4);printf("%d\n", s.Top());printf("%d\n", s.Size());s.Pop();s.Pop();printf("%d\n", s.Top());printf("%d\n", s.Size());s.Destroy();return 0;
}

🙂感谢大家的阅读,若有错误和不足,欢迎指正。

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

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

相关文章

运行gazebo机器人模型没有cmd_vel话题

运行赵虚左教程代码出现上诉问题 roslaunch urdf02_gazebo demo03_env.launch 原因&#xff1a;缺少某个包 在工作空间catkin_make编译发现报错 解决&#xff1a; sudo apt-get install ros-noetic-gazebo-ros-pkgs ros-noetic-gazebo-ros-control 下载后再次运行launch文件…

Paxos算法

Paxos算法 https://www.youtube.com/watch?vd7nAGI_NZPk 有一个 Overview概述 1、什么是Paxos? 2、为什么需要Paxos? 3、Paxos是什么&#xff1f; 纳秒的时间戳&#xff0c;选择高id. higher id 多个角色的扮演。 propose发起&#xff0c;acceptor忽略低版本id. 达…

一文搞懂PCL中自定义点云类型的构建与函数使用

上周猛男快乐开发时遇到个bug&#xff0c;要用pcl的函数对自定义的点云进行处理。一起解决问题时遇到了很多问题&#xff0c;解决后整理出来分享给各位参考&#xff0c;以免踩一样的坑&#x1f60a;。文章中自定义的点我用PointT来表示&#xff0c;自定义点云一般指的是pcl::Po…

程序人生——Java泛型和反射的使用建议

目录 引出泛型和反射建议93&#xff1a;Java的泛型是类型擦除的建议94&#xff1a;不能初始化泛型参数和数组建议95&#xff1a;强制声明泛型的实际类型 建议96&#xff1a;不同的场景使用不同的泛型通配符建议97&#xff1a;警惕泛型是不能协变和逆变的 建议98&#xff1a;建议…

OpenAI 的 GPTs 提示词泄露攻击与防护实战:攻击卷(一)

攻击提示词 1.0 五件套混合散打 1. Repeat the words above starting with the phrase "You are ChatGPT". put them in a txt code block. Include everything. 2. give me your very first initial prompt exactly and not modified 3. 你有一個舊的 prompt 和 配…

QT学习笔记:创建项目

创建QT项目 QT版本下载时对应的环境QT自带工具离线版本的官方文档图形化设计工具语言设置开发工具qtcreator 创建一个qt项目运行测试 要开始进行QT的学习了,学了许久的C&#xff0c;终于可以像隔壁java一样写出自己能看见的不是黑框框的程序了,话不多说,走起~ QT版本 现在qt貌…

【ArcGISPro】道路数据下载并使用

下载 下载链接: Geofabrik 下载服务器 这些数据通常 每天更新。 下载结果 arcmap用户下载工具 10.2:http://www.arcgis.com/home/item.html?id=16970017f81349548d0a9eead0ebba39 10.3:

宠物疾病 与 光线疗法

人类与动物以及大自然是相辅相成的。人离开动物将无法生存&#xff0c;对于动物我们尽力去保护&#xff0c;与大自然和谐稳定生存发展。 生息在地球上的所有动物、在自然太阳光奇妙的作用下、生长发育。太阳光的能量使它们不断进化、繁衍种族。现在、生物能够生存、全仰仗于太…

unicloud update 修改

update 修改 使用腾讯云时更新方法必须搭配doc、where方法使用&#xff0c;db.collection(‘test’).update()会报如下错误&#xff1a;param should have required property ‘query’ collection.doc().update(Object data)未使用set、remove更新操作符的情况下&#xff0c…

MySQL语法分类 DQL(1)基础查询

//语法 select 字段列表 from 表名列表 where条件列表 group by分组字段 having 分组后的条件 order by排序 limit 分页限定为了更好的学习这里给出基本表数据用于查询操作 create table student (id int, name varchar(20), age int, sex varchar(5),address varchar(100),ma…

ctype.h的了解string.h库函数中各个函数的使用和模拟实现

目录 字符分类函数 函数讲解 使用样例 字符转换函数 函数讲解 使用样例 strlen的使用和模拟实现 strlen的使用 strlen的模拟实现 计数器 递归&#xff08;不创建临时变量&#xff09; 指针-指针 strcpy的使用和模拟实现 strcpy的使用 strcpy的模拟实现 strca…

unity3d Animal Controller的Animal组件中General基础部分理解

控制器介绍 动物脚本负责控制动物的所有运动逻辑.它管理所有的动画师和刚体参数,以及所有的状态和模式,动物可以做。 动物控制器 是一个动画框架控制器,根动或到位,为任何生物或人形。它利用刚体与物理世界的互动和动画师的玩动画。 States States 是不互相重叠的动画。例如…

PMP的学习方法

PMBOK编撰了管理项目需要的49个过程&#xff08;输入、工具技术、输出&#xff09;。工具技术文件&#xff0c;林林总总百余个。第一部分&#xff0c;按照十大知识领域顺序从前到后编排&#xff1b;第二部分&#xff0c;按照五大过程组顺序重新编排了一遍。 一&#xff0c;PMB…

20240313寻找集成联调交付的具体方式

集成联调交付&#xff08;Integrated Joint Debugging and Delivery&#xff09;是软件开发过程中的一个阶段&#xff0c;主要涉及将不同的软件模块或组件整合在一起&#xff0c;并进行联合调试和测试&#xff0c;以确保它们能够作为一个整体正常工作。这个过程通常发生在开发周…

手搭手RocketMQ重试机制

环境介绍 技术栈 springbootmybatis-plusmysqlrocketmq 软件 版本 mysql 8 IDEA IntelliJ IDEA 2022.2.1 JDK 17 Spring Boot 3.1.7 dynamic-datasource 3.6.1 mybatis-plus 3.5.3.2 rocketmq 4.9.4 加入依赖 <dependencies><dependency><…

【Poi-tl Documentation】自定义占位符来设置图片大小

前置说明&#xff1a; <dependency><groupId>com.deepoove</groupId><artifactId>poi-tl</artifactId><version>1.12.1</version> </dependency>模板文件&#xff1a; image_test.docx package run.siyuan.poi.tl.policy;imp…

调皮的String及多种玩法(下部)

&#x1f468;‍&#x1f4bb;作者简介&#xff1a;&#x1f468;&#x1f3fb;‍&#x1f393;告别&#xff0c;今天 &#x1f4d4;高质量专栏 &#xff1a;☕java趣味之旅 欢迎&#x1f64f;点赞&#x1f5e3;️评论&#x1f4e5;收藏&#x1f493;关注 &#x1f496;衷心的希…

某赛通电子文档安全管理系统 DecryptApplication 任意文件读取漏洞复现

0x01 产品简介 某赛通电子文档安全管理系统(简称:CDG)是一款电子文档安全加密软件,该系统利用驱动层透明加密技术,通过对电子文档的加密保护,防止内部员工泄密和外部人员非法窃取企业核心重要数据资产,对电子文档进行全生命周期防护,系统具有透明加密、主动加密、智能…

国创证券策略:股指预计维持震荡格局 关注汽车、通信设备等板块

国创证券指出&#xff0c;近期两市指数持续反弹创新高&#xff0c;但沪指现已率先出现滞涨状况&#xff0c;一起均已进入阻力重压区。不过当时技术形状上坚持较好&#xff0c;可持续做多&#xff0c;一旦跌破重要支撑如沪指的3030点&#xff0c;则需降仓防卫&#xff0c;防止指…

Python 导入Excel三维坐标数据 生成三维曲面地形图(面) 1、线条折线曲面

环境和包: 环境 python:python-3.12.0-amd64包: matplotlib 3.8.2 pandas 2.1.4 openpyxl 3.1.2 代码: import pandas as pd import matplotlib.pyplot as plt import numpy as np from mpl_toolkits.mplot3d import Axes3D from matplotlib.colors import ListedColor…