c++初阶知识——类和对象(1)

目录

1.类和对象

1.1 类的定义

1.2 访问限定符

1.3 类域

 2.实例化

2.1 实例化概念

2.2 对象大小 

内存对齐规则 

3.this指针


1.类和对象

1.1 类的定义

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

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
class Stack
{
public:// 成员函数void Init(int n = 4){array = (int*)malloc(sizeof(int) * n);if (nullptr == array){perror("malloc申请空间失败");return;}capacity = n;top = 0;}void Push(int x){// ...扩容arr[top++] = x;}int Top(){assert(top > 0);return array[top - 1];}void Destroy(){free(array);array = nullptr;top = capacity = 0;}private:int* arr;int size;int capacity;
};
int main()
{Stack st;st.Init();st.Push(1);st.Push(2);cout << st.Top() << endl;st.Destroy();return 0;}

(2)为了区分成员变量,⼀般习惯上成员变量会加⼀个特殊标识,如成员变量前⾯或者后⾯加_ 或者 m开头,注意C++中这个并不是强制的,只是⼀些惯例,具体看公司的要求。

class Date
{
public:
void Init(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
private:
// 为了区分成员变量,⼀般习惯上成员变量
// 会加⼀个特殊标识,如_ 或者 m开头
int _year; // year_ m_year
int _month;
int _day;
};
int main()
{
Date d;
d.Init(2024, 3, 31);
return 0;
}

(3)C++中struct也可以定义类,C++兼容C中struct的⽤法,同时struct升级成了类,明显的变化是struct中可以定义函数,区别是使用struct定义的类的成员默认为public,而class定义的类的成员默认为private(public和private定义后面会讲到),⼀般情况下我们还是推荐⽤class定义类。

#include<iostream>
using namespace std;
// C++升级struct升级成了类
// 1、类⾥⾯可以定义函数
// 2、struct名称就可以代表类型
// C++兼容C中struct的⽤法
typedef struct ListNodeC
{
struct ListNodeC* next;
int val;
}LTNode;
// 不再需要typedef,ListNodeCPP就可以代表类型
struct ListNodeCPP
{
void Init(int x)
{
next = nullptr;
val = x;
}
ListNodeCPP* next;
int val;
};
int main()
{
return 0;
}

 (4)定义在类⾯的成员函数默认为inline。

1.2 访问限定符

 (1)C++⼀种实现封装的⽅式,⽤类将对象的属性与⽅法结合在⼀块,让对象更加完善,通过访问权限选择性的将其接⼝提供给外部的⽤⼾使⽤

(2)public修饰的成员在类外可以直接被访问;protected和private修饰的成员在类外不能直接被访问,protected和private是⼀样的,以后继承章节才能体现出他们的区别。

(3)问权限作⽤域从该访问限定符出现的位置开始直到下⼀个访问限定符出现时为⽌,如果后⾯没有访问限定符,作⽤域就到 }即类结束。

(4)class定义成员没有被访问限定符修饰时默认为privatestruct默认为public

(5)⼀般成员变量都会被限制为private/protected,需要给别⼈使⽤的成员函数会放为public。

【面试题】

问题:C++中struct和class的区别是什么?

解答:C++需要兼容C语言,所以C++中struct可以当成结构体使用。另外C++中struct还可以用来
定义类。和class定义类是一样的,区别是struct定义的类默认访问权限是public,class定义的类
默认访问权限是private。注意:在继承和模板参数列表位置,struct和class也有区别,后序给大
家介绍。

1.3 类域

(1)类定义了⼀个新的作⽤域,类的所有成员都在类的作⽤域中,在类体外定义成员时,需要使⽤ :: 作⽤域操作符指明成员属于哪个类域。

(2)类域影响的是编译的查找规则,下⾯程序中Init如果不指定类域Stack,那么编译器就把Init当成全局函数,那么编译时,找不到array等成员的声明/定义在哪⾥,就会报错。指定类域Stack,就是知道Init是成员函数,当前域找不到的array等成员,就会到类域中去查找。

#include<iostream>
using namespace std;
class Stack
{
public:
// 成员函数
void Init(int n = 4);private:
// 成员变量
int* array;
size_t capacity;
size_t top;
};
// 声明和定义分离,需要指定类域
void Stack::Init(int n)
{
array = (int*)malloc(sizeof(int) * n);
if (nullptr == array)
{
perror("malloc申请空间失败");
return;
}
capacity = n;
top = 0;
}
int main()
{
Stack st;
st.Init();
return 0;
}

 2.实例化

2.1 实例化概念

(1)⽤类类型在物理内存中创建对象的过程,称为类实例化出对象。

(2)类是对象进⾏⼀种抽象描述,是⼀个模型⼀样的东西,限定了类有哪些成员变量,这些成员变量只是声明,没有分配空间,⽤类实例化出对象时,才会分配空间。

(3)⼀个类可以实例化出多个对象,实例化出的对象 占⽤实际的物理空间,存储类成员变量。打个⽐⽅:类实例化出对象就像现实中使⽤建筑设计图建造出房⼦,类就像是设计图,设计图规划了有多少个房间,房间⼤⼩功能等,但是并没有实体的建筑存在,也不能住⼈,⽤设计图修建出房⼦,房⼦才能住⼈。同样类就像设计图⼀样,不能存储数据,实例化出的对象分配物理内存存储数据。

代码实例:

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
class Data
{
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和d2Data d1;Data d2;d1.Init(2024, 9,9);d1.print();d2.Init(1919, 5, 4);d2.print();return 0;
}

2.2 对象大小 

   分析⼀下类对象中哪些成员呢?类实例化出的每个对象,都有独⽴的数据空间,所以对象中肯定包含成员变量,那么成员函数是否包含呢?⾸先函数被编译后是⼀段指令,对象中没办法存储,这些指令存储在⼀个单独的区域(代码段),那么对象中⾮要存储的话,只能是成员函数的指针。

再分析⼀下,对象中是否有存储指针的必要呢,Date实例化d1和d2两个对象,d1和d2都有各⾃独⽴的成员变量_year/_month/_day存储各⾃的数据,但是d1和d2的成员函数Init/Print指针却是⼀样的,存储在对象中就浪费了。

如果⽤Date实例化100个对象,那么成员函数指针就重复存储100次,太浪费了。这⾥需要再额外啰嗦⼀下,其实函数指针是不需要存储的,函数指针是⼀个地址,调⽤函数被编译成汇编指令[call 地址], 其实编译器在编译链接时,就要找到函数的地址,不是在运⾏时找,只有动态多态是在运⾏时找,就需要存储函数地址,这个我们以后会讲解

 

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

内存对齐规则 

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

(2)其他成员变量要对⻬到某个数字(对⻬数)的整数倍的地址处。

(3)注意:对⻬数 = 编译器默认的⼀个对⻬数 与 该成员⼤⼩的较⼩值。

(4)VS中默认的对⻬数为8

(5)构体总⼤⼩为:最⼤对⻬数(所有变量类型最⼤者与默认对⻬参数取最⼩)的整数倍。

(6)如果嵌套了结构体的情况,嵌套的结构体对⻬到⾃⼰的最⼤对⻬数的整数倍处,结构体的整体⼤⼩就是所有最⼤对⻬数(含嵌套结构体的对⻬数)的整数倍。

3.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指针。

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

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

相关文章

达梦数据库中的线程和进程

达梦数据库中的线程和进程 在达梦数据库中&#xff0c;线程和进程的概念与操作系统中的定义类似&#xff0c;但有一些特定的实现细节和用途。以下是达梦数据库中线程和进程的一些关键点&#xff1a; 进程&#xff08;Process&#xff09;&#xff1a; 在达梦数据库中&#x…

mysql数据库被偷家,数据全部丢失。还勒索我给他比特币

歹徒留下的勒索信息。 解决办法&#xff1a; 1、设置ip白名单&#xff0c; 2、端口不要使用默认端口&#xff0c;随便换个端口就行。 3、密码设置复杂一点。

【Java16】多态

向上类型转换 对于引用变量&#xff0c;在程序中有两种形态&#xff1a;一种是编译时类型&#xff0c;这种引用变量的类型在声明它的时候就决定了&#xff1b;另一种则是运行时类型&#xff0c;这种变量的类型由实际赋给它的对象决定。 当一个引用变量的编译时类型和运行时类…

【Pytorch】Conda环境pack打包迁移报错处理

文章目录 Anaconda虚拟环境打包一、源电脑的环境打包1.安装conda-pack工具2.确定环境3.打包环境4.将打包环境拷贝到U盘 二、环境迁移到目标电脑上三、异常处理pip install -e. 导致无法pack→忽略管理的文件已经被删除或者被覆盖→压缩成tar注意 重新激活环境 Anaconda虚拟环境…

14 - matlab m_map地学绘图工具基础函数 - 一些数据转换函数(一)

14 - matlab m_map地学绘图工具基础函数 - 一些数据转换函数&#xff08;一&#xff09; 0. 引言1. 关于m_ll2xy和m_xy2ll2. 关于m_lldist3. 关于m_xydist4 关于m_fdist5 关于m_idist6. 总结 0. 引言 通过前面篇节已经将m_map绘图工具中大多绘图有关的函数进行过介绍&#xff0…

Nuxt3封装网络请求 useFetch $fetch

前言&#xff1a; 刚接触、搭建Nuxt3项目的过程还是有点懵的&#xff0c;有种摸石头过河的感觉&#xff0c;对于网络请求这块&#xff0c;与之前的Vue3项目有所区别&#xff0c;在Vue项目通常使用axios这个库进行网络请求&#xff0c;但在Nuxt项目并不推荐&#xff0c;因为有内…

RK3568平台(显示篇)主屏副屏配置

一.主屏副屏配置 目前在RK3568平台上有两路HDMIOUT输出&#xff0c;分别输出到两个屏幕上&#xff0c;一路配置为主屏&#xff0c;一路配置为副屏。 硬件原理图&#xff1a; &hdmi0_in_vp2 {status "okay"; };&hdmi1_in_vp0 {status "okay"; }…

axios使用sm2加密数据后请求参数多了双引号解决方法

axios使用sm2加密数据后请求参数多了双引号解决 背景问题描述解决过程 背景 因项目安全要求&#xff0c;需对传给后端的入参加密&#xff0c;将请求参数加密后再传给后端 前期将axios降低到1.6.7后解决了问题&#xff0c;但最近axios有漏洞&#xff0c;安全要求对版本升级&…

【Qt 初识 Test】用图形化和代码的方式实现简单的Qt程序

文章目录 1. 通过图形化的方式实现&#x1f34e;2. 通过代码的方式实现 1. 通过图形化的方式实现&#x1f34e; 在界面创建出一个控件&#xff0c;显示 hello world&#xff0c;通过拖拽的方式实现&#xff1b; widget.ui文件如下&#xff1a;&#x1f50d; 生成的 ui_widget.…

【mybatis】mybatisX插件概述

一、主要功能 智能补全与提示 MyBatisX 可以智能地提示和补全 SQL 语句中的关键字、表名、列名等信息&#xff0c;从而显著提高开发效率。代码生成器 虽然 MyBatisX 本身可能不直接提供一个完整的、独立的代码生成器&#xff0c;但它可能集成了或支持与其他代码生成工具&#…

卤味江湖中,周黑鸭究竟该抓住什么赛点?

近年来&#xff0c;卤味江湖的决斗从未停止。 随着休闲卤味、佐餐卤味等细分赛道逐渐形成&#xff0c;“卤味三巨头”&#xff08;周黑鸭、绝味食品、煌上煌&#xff09;的牌桌上有了更多新对手&#xff0c;赛道变挤了&#xff0c;“周黑鸭们”也到了转型关键期。 这个夏天&a…

MySQL字符串相关数据处理函数

目录 1. 转大小写 2. 截取字符串 sunstr 3. 获取字符长度 4. 字符串拼接 concat 5. 去掉空白 trim 1. 转大小写 转大写&#xff1a;upper() 转小写&#xff1a;lower() 虽然MySQL不严格区分大小写&#xff0c;但是我们还是需要掌握这种大小写的操作以方便学习其他…

Nessus相关

tenable 1 安装nessus scanner 1 )安装nessus scanner: 方法一 curl -H X-Key: xxxxx https://cloud.tenable.com/install/scanner?namescanner-name&groupsscanner-group | bash方法二&#xff1a; **# for ubuntu, its https://www.tenable.com/downloads/api/v1/pu…

Google登录时人机身份验证的图片类型和通过的经验建议,以及一些常见问题

很多朋友在登录谷歌账号时&#xff0c;都遇到过要求人机身份验证的步骤&#xff0c;而且有一些时候人机身份验证这个步骤很让人纠结&#xff0c;甚至压根就出不来具体的验证图片&#xff0c;或者花了十几分钟、几十分钟都过不去。 所以今天GG账号服务就来为您解析一下谷歌登录…

初学SpringMVC之接收请求参数及数据回显

pom.xml 文件导入 lombok 的依赖 <dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.34</version></dependency> Controller 表示这是一个控制器 RequestParam 表示从前端接收…

夏日智启:我的Datawhale AI夏令营探索之旅

前言 最近几年&#xff0c;AI&#xff08;人工智能&#xff09;的发展呈现出了前所未有的迅猛势头&#xff0c;其影响力和应用范围不断扩大&#xff0c;深刻地改变着我们的生活、工作和社会结构。尤其是AI大模型技术&#xff0c;国内外可谓是“百模大战”&#xff0c;百舸争流…

github恢复码怎么备份

https://docs.github.com/zh/authentication/securing-your-account-with-two-factor-authentication-2fa/configuring-two-factor-authentication-recovery-methods

谷歌插件之一键关闭同域名页面

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 &#x1f38f;&#xff1a;你只管努力&#xff0c;剩下的交给时间 &#x1f3e0; &#xff1a;小破站 谷歌插件之一键关闭同域名页面 前言项目结构mainfest.jsonbackgroud.js 项目实现效果展示展望 前…

13019.CUDA问题积累

文章目录 1 内存不断增长的问题1.1 主机从GPU拷贝内存1.1.1 htop 内存增长到一定阶段后&#xff0c;保持稳定 1.2 GPU拷贝到Host修改之后内存稳定无变化1.3 结论 2 主机与GPU数据拷贝方案2.1 cudaMemcpy 拷贝内存2.2 cudaMemcpyAsync 异步数据拷贝2.3 采用多线程拷贝技术2.3.1 …

群主必学!轻松Get如何解散微信群的技巧

作为一个微信群的群主&#xff0c;解散群聊可能是你需要掌握的重要技能之一。不管是因为群聊的目的已经达成&#xff0c;还是因为群成员过少或不活跃&#xff0c;了解如何解散微信群都能帮助你更好地管理你的群聊。 如何解散微信群&#xff1f;本文将为您提供一些简单易行的技…