C++-类与对象基础

一,类的定义

1.1类定义格式

class为定义类的关键字,Stack为类的名字,{}中为类的主体,注意类定义结束时后面分号不能省略。类体中内容称为mian类的成员:类中的变量称为类的属性或成员变量; 类中的函数称为类的方法或者成员函数。比如我们下面的一个简单的栈结构例子(不完整,作为引子使用):

using namespace std;class Stack
{
public:void Init(int n = 4){int* tmp = (int*)malloc(sizeof(int) * n);if (tmp == nullptr){perror("realloc fail!");exit(EXIT_FAILURE);}_arr = tmp;top = 0;capacity = n;}void Destory(){free(_arr);_arr = nullptr;top = capacity = 0;}
private:int* _arr;int top;int capacity;
};int main()
{Stack d1;d1.Destory();return 0;
}

我们可以看到,类的使用方法与我们C中所学习的结构体非常类似,且class定义的类名可以直接代表类型,不需要我们再去使用typedef,而我们的C++中strcut也升级为了类,在struct中可以定义函数,但我们一般还是在C++中使用class定义类。

除此之外,我们的类的成员函数前都默认加有我们的inline:

void Init(int n = 4)//inline void Init(int n = 4)
{int* tmp = (int*)malloc(sizeof(int) * n);if (tmp == nullptr){perror("realloc fail!");exit(EXIT_FAILURE);}_arr = tmp;top = 0;capacity = n;
}

1.2访问限定符

我们注意到,在上面的栈代码中有public与private,这就是我们的类的访问限定符,我们的类访问限定符一共有三种:

1.public修饰的成员在类外可以直接被访问;protected和private修饰的成员在类外不能直接被访问,protected和private是⼀样的,以后介绍到继承部分时才能体现出他们的区别。

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

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

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

1.3类域 

这部分其实与我们的namespace有些许类似,类域影响的是编译的查找规则,就比如说我们要直接使用上面代码中的Init函数,如果不指定类域Stack,那么编译器就把Init当成全局函数,那么编译时,找不到arr等成员的声明/定义在哪里,就会报错。指定类域Stack,就是知道Init是成员函数,当前域找不到的arr等成员,就会到类域中去查找。

class Stack
{
public:void Init(int n = 4){int* tmp = (int*)malloc(sizeof(int) * n);if (tmp == nullptr){perror("realloc fail!");exit(EXIT_FAILURE);}_arr = tmp;top = 0;capacity = n;}
private:int* _arr;int top;int capacity;
};int main()
{Stack::Init();//正确调用方法Init();//编译器找不到Init函数return 0;
}

二,实例化

 2.1实例化的概念

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

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

3.⼀个类可以实例化出多个对象,实例化出的对象占用实际的物理空间,存储类成员变量。所以简单来说,我们的类就像盖房子的图纸一样,对着图纸建造出我们的房子就是我们的实例化。

2.2对象大小

我们在上面说过,类的定义中是有函数的,成员变量的大小我们在C语言中就已经详细了解过了,不多赘述。我们来看类的成员函数,假如我们的成员函数也是占有空间的,那我们去定义100个类,是不是就要去至少实例化100个成员函数,但我们知道,在实际使用的时候,拿我们上面的Stack来举例:

class Stack
{
public:void Init(int n = 4){int* tmp = (int*)malloc(sizeof(int) * n);if (tmp == nullptr){perror("realloc fail!");exit(EXIT_FAILURE);}_arr = tmp;top = 0;capacity = n;}void Destory(){free(_arr);_arr = nullptr;top = capacity = 0;}
private:int* _arr;int top;int capacity;
};int main()
{Stack d1;Stack d2;d1.Destory();d2.Destory();return 0;
}

可以看到,两个相同的类用的是同一个函数,这样不就造成了不必要的实例化了。其实,函数被编译后是⼀段指令,对象中没办法存储,这些指令存储在⼀个单独的区域(代码段),那么对象中非要存储的话,只能是成员函数的指针。同时函数指针是不需要存储的,函数指针是⼀个地址,调用函数被编译成汇编指令[call 地址], 其实编译器在编译链接时,就要找到函数的地址,不是在运行时找,只有动态多态是在运行时找,就需要存储函数地址,这个我们以后的文章会介绍。

 接下来我们来看几个例子:

class A
{public :void Print(){cout << _ch << endl;}
private:char _ch;int _i;
};
class B
{public :void Print(){//...}
};
class C
{};

对于A,我们可以轻松的算出其大小为8byte,但是C和B呢。猛一看,我们上面不是说过,只有实例化的对象才会分配空间,所以按照常理来说B和C均为0,但是实际上为1,为什么?

B b1;
C c1;

如果为0,那我们上面定义的两个b1和c1所分配的空间就是0,如果⼀个字节都不给,怎么表示对象存在过呢,所以这里给1字节,纯粹是为了占位标识对象存在。

三,this指针

当我们定义了两个Stack对象时,编译器是如何区分d1与d2呢。事实上,编译器会在编译的时候自动在后面补上一个this指针:
 

d1.Init(&d1);
d2.Init(&d2);void Init(int n = 4)//实际调用后void Init(Stack const* this,int n = 4)
{int* tmp = (int*)malloc(sizeof(int) * n);if (tmp == nullptr){perror("realloc fail!");exit(EXIT_FAILURE);}_arr = tmp;top = 0;capacity = n;
}

所以类的成员函数中访问成员变量,本质都是通过this指针访问的。除此之外,C++规定不能在实参和形参的位置显示的写this指针(编译时编译器会处理),但是可以在函数体内显示使用this指针。

下面让我们来看两个经典案例:

乍一看两个都对空指针进行了解引用,二者均会产生运行崩溃(切记编译错误为语法上的错误),但实际上只有第二种情况会报错。我们上面也说过,成员函数的调用与我们定义的对象没有关系,他们的使用实际是直接call使用的:

所以在第一种情况下并没有发生对空指针的解引用,但第二种则是需要成员变量去完成函数运转,所以会发生对空指针的解引用,进而导致编译报错。

四,C++中struct与class的区别

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

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

相关文章

【nginx】centos7安装并配置开机自启

【nginx】配置开机自启 1.nginx配置开机自启 安装完成nginx之后 vim /lib/systemd/system/nginx.service[Unit] Descriptionnginx Afternetwork.target[Service] Typeforking ExecStart/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf ExecReload/usr/loc…

理解Spring框架2:容器IOC

理解Spring框架2&#xff1a;容器IOC (qq.com)

ViP-LLaVA: Making Large Multimodal Models Understand Arbitrary Visual Prompts

发表时间&#xff1a;cvpr2024 论文链接&#xff1a;https://readpaper.com/pdf-annotate/note?pdfId2357936887983293952&noteId2426262228488986112 作者单位&#xff1a;University of Wisconsin–Madison Motivation&#xff1a;现在的多模态模型都关注整张图像的理…

torch量化接口深度解读-eager模式-fx模式

一、定义 接口总结量化模式解读 二、实现 接口总结 1. PyTorch提供了三种不同的量化模式&#xff1a;Eager模式量化、FX图模式量化&#xff08;维护&#xff09;和PyTorch 2导出量化。 2. Eager Mode Quantization是一个测试版功能。用户需要进行融合&#xff0c;并手动指定量…

尚硅谷谷粒商城项目笔记——六、使用navciat连接docker中的mysql容器【电脑CPU:AMD】

六、使用navciat连接docker中的mysql容器 注意&#xff1a; 因为电脑是AMD芯片&#xff0c;自己知识储备不够&#xff0c;无法保证和课程中用到的环境一样&#xff0c;所以环境都是自己根据适应硬件软件环境重新配置的&#xff0c;这里的虚拟机使用的是VMware。 1navicat免费…

最新版Ableton Live 12.20 WIN MAC,长期更新持续有效

一。Ableton Live 12.20 WIN &MAC 2024.08.06发布 Ableton Live Suite是一款由ABLETON公司开发的功能强大且全面的音乐制作、内容编辑和演奏分析软件。它极大地改进了许多社会功能&#xff0c;使音乐创作、背景音乐的开发变得更加快捷方便。 软件的主要功能包括录音、作曲…

WordPress原创插件:Category-id-list分类ID显示查看

WordPress原创插件&#xff1a;Category-id-list分类ID显示查看 插件设置位置在工具栏

学习vue3 五,传送,缓存组件以及过渡和过渡列表

目录 Teleport传送组件 keep-alive缓存组件 transition动画组件 1. 过渡的类名 2. 自定义过渡class名 3. transition的生命周期 4.appear transition-group 1. 过渡列表 2. 列表的移动过渡 3. 状态过渡 Teleport传送组件 Teleport Vue 3.0新特性之一。 Teleport 是一…

Spring的配置类分为Full和Lite两种模式

Spring的配置类分为Full和Lite两种模式 首先查看 Configuration 注解的源码, 如下所示: Target({ElementType.TYPE}) Retention(RetentionPolicy.RUNTIME) Documented Component public interface Configuration {AliasFor(annotation Component.class)String value() defau…

(C23/C++23) 语句末尾的标签

文章目录 &#x1f516;前言&#x1f3f7;️ref&#x1f3f7;️标号 &#x1f516;兼容&#x1f3f7;️23标准前&#x1f3f7;️23标准后&#x1f3f7;️原因 &#x1f516;未兼容&#x1f516;END&#x1f31f;关注我 &#x1f516;前言 &#x1f3f7;️ref C23提案复合语句末…

Serverless 1

一、云原生应用 云原生应用覆盖到&#xff1a; 大数据&#xff0c;人工智能&#xff0c;边缘计算&#xff0c;区块链等 服务代理&#xff1a;envoy API 网关&#xff1a;APISIX 服务网格&#xff1a;Istio 服务发现&#xff1a;CoreDNS 消息和流式处理&#xff1a;kafka Serve…

PDF预览:利用vue3-pdf-app实现前端PDF在线展示

目录 PDF预览&#xff1a;利用vue3-pdf-app实现前端PDF在线展示 一、vue3-pdf-app组件介绍及其优点 1、vue3-pdf-app是什么 2、作用与场景 3、类似的插件 二、项目初始化与依赖安装 1、初始化Vue3项目 2、安装依赖 三、集成vue3-pdf-app插件 1、引入插件 2、配置组件…

ChemLLM化学大模型再升级,AI助力化学研究

ChemLLM 介绍 ChemLLM 系列模型 是由上海人工智能实验室基于InternLM2 开发的首个兼备化学专业能力和对话、推理等通用能力的开源大模型。相比于现有的其他大模型&#xff0c;ChemLLM 对化学空间进行了有效建模&#xff0c;在分子、反应和其他领域相关的化学任务上表现优异。 …

解决戴尔台式电脑休眠后无法唤醒问题

近期发现有少量戴尔的台式机会有休眠后无法唤醒的问题&#xff0c;具体现象就是电脑在休眠后&#xff0c;电源指示灯以呼吸的频率闪烁&#xff0c;无论怎么点鼠标和键盘都没有反应&#xff0c;并且按开机按钮也没法唤醒&#xff0c;只能是长按开机键强制关机再重启才行&#xf…

leetcode 958.二叉树的完全性检验

1.题目要求: 给你一棵二叉树的根节点 root &#xff0c;请你判断这棵树是否是一棵 完全二叉树 。在一棵 完全二叉树 中&#xff0c;除了最后一层外&#xff0c;所有层都被完全填满&#xff0c;并且最后一层中的所有节点都尽可能靠左。最后一层&#xff08;第 h 层&#xff09;…

YOLOv8改进 | 主干网络 | 将backbone替换为MobileNetV4【小白必备教程+附完整代码】

秋招面试专栏推荐 &#xff1a;深度学习算法工程师面试问题总结【百面算法工程师】——点击即可跳转 &#x1f4a1;&#x1f4a1;&#x1f4a1;本专栏所有程序均经过测试&#xff0c;可成功执行&#x1f4a1;&#x1f4a1;&#x1f4a1; 专栏目录 &#xff1a;《YOLOv8改进有效…

Linux PCI和PCIe总线

1 PCIe中断 - PCI/PCIe设备中断都是level触发&#xff0c;并且请求信号为低电平有效 - PCI总线一般只有INTA#到INTD#的4个中断引脚&#xff0c;所以PCI多功能设备的func一般不会超过4个&#xff0c;但是共享中断除外 2 IOMMU 2.1 ARM SMMU v2 Refer to my blog ARM SMMU v2. 2.…

【机器学习】重塑游戏世界:机器学习如何赋能游戏创新与体验升级

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀目录 &#x1f50d;1. 引言&#xff1a;游戏世界的变革前夜&#x1f4d2;2. 机器学习驱动的游戏创新&#x1f31e;智能化游戏设计与开发&…

OJ-0807

题目 参考 import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner in new Scanner(System.in);String input in.nextLine();String[] numStrs inp…

身体出现这5种异常,可能是甲状腺在求救,千万别扛着!

甲状腺&#xff0c;被誉为人体新陈代谢的“发动机”&#xff0c;是调节我们身体能量和代谢的重要器官。然而&#xff0c;当甲状腺出现问题时&#xff0c;它往往会通过身体的一些异常信号向我们求救。北京精诚博爱医院张维一主任提醒&#xff1a;以下是五种常见的甲状腺异常表现…