C++:类与对象(上)

C++:类与对象(上)

    • 类的引入
    • 类的定义
    • 访问限定符
    • 类域
    • 实例化
    • 对象模型
    • this指针


类的引入

C++的类是基于C语言的结构体优化出来的,那我们先来看一看C++对结构体有哪些优化点。

C语言与C++的结构体的类型名称略有区别,我们看一个案例:

//C语言的结构体
struct ListNode1
{int val;struct ListNode1* next;
};//C++的结构体
struct ListNode2
{int val;ListNode2* next;
};int main()
{struct ListNode1 L1;//C语言的结构体创建变量ListNode2 L2;//C++的结构体创建变量
}

一开始我们定义了两个结构体:ListNode1ListNode2,在mian函数中我们分别对两个结构体创建了变量。
在C语言的结构体创建的变量时,需要用struct ListNode1作为类型来创建。
而在C++的结构体创建变量时,只需要ListNode2作为类型来创建。

也就是说,在C语言中结构体创建变量需要加上struct关键字,而C++中优化了,可以无需这个关键字。

所以我们在结构体内部定义的next节点的指针,也分别是struct ListNode1*ListNode2*

C语言中结构体只能用于定义变量,但是在C++中,结构体内不仅可以定义变量,还可以定义函数

struct stack
{void Init(){cout << "初始化栈" << endl;}void Push(int x){cout << x << "被压栈了" << endl;}void Destroy(){cout << "销毁栈" << endl;}int stackSize(){return size;}int* a;int size;int capacity;
};

上述代码中,我们定义了一个stack结构体,其内部有asizecapacity三个基本变量,这是在C语言结构体范围内的。但是我们还额外定义了几个函数在其内部InitPushDestroy以及stackSize。我们可以通过结构体来调用某一个函数。

那么要如何调用函数?
其实只要把函数当作一个普通的变量,用.操作符访问即可。
在这里插入图片描述
这样我们就正常访问到了结构体内部的函数。

我们看到结构体内的一个函数:

int stackSize()
{return size;
}

这个函数里面没有size这个形参,为什么可以直接使用size?
在同一个结构体内部的变量,是可以直接被结构体内的函数访问到的。因为size存在于结构体中,所以结构体内的函数可以访问到size

但是为了更好的区别C语言的结构体与C++的结构体,C++更喜欢用一种叫做类的结构来替代结构体。


类的定义

class关键字是定义类的关键字,在C++中,直接使用class代替struct即可,而我上方说的所有C++对结构体的优化,在类中也使用。

上述结构体可以定义为以下的类:

class stack
{void Init(){cout << "初始化栈" << endl;}void Push(int x){cout << x << "被压栈了" << endl;}void Destroy(){cout << "销毁栈" << endl;}int stackSize(){return size;}int* a;int size;int capacity;
};

其中函数部分叫做成员函数或者方法,变量部分叫做类的属性或者成员变量

但是这样定义类会有一个问题:
在这里插入图片描述
为什么我们定义的类,无法访问到其内部的函数了???

这是因为对于类来说,其所有成员会被分为公有和私有,接下来我们看看什么是公有私有,以及如何转换:


访问限定符

在这里插入图片描述

  1. public修饰的成员在类外可以直接被访问
  2. protectedprivate修饰的成员在类外不能直接被访问(这方面protectedprivate是类似的)
  3. 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
  4. 如果后面没有访问限定符,作用域就到} 即类结束。
  5. class的默认访问权限为privatestructpublic(因为struct要兼容C语言)

首先看到第1,2点: public修饰的成员,在类外部可以直接访问,而 protectedprivate修饰的成员在类外不能直接被访问。
再看到第五点: class的默认访问权限为privatestructpublic

也就是说,class定义的类,默认外部无法访问到其内部的成员,所以当我们把struct转为 class,外部访问函数就报错了。

所以以上代码要改为:

class stack
{
public:void Init(){cout << "初始化栈" << endl;}void Push(int x){cout << x << "被压栈了" << endl;}void Destroy(){cout << "销毁栈" << endl;}int stackSize(){return size;}int* a;int size;int capacity;
};

这样整个类都可以被外部访问了,因为所有的成员都在public下方。
但是我们很多时候不希望别人修改我们的数据,只希望别人调用函数。

所以我们可以把成员变量改为私有:

class stack
{
public:void Init(){cout << "初始化栈" << endl;}void Push(int x){cout << x << "被压栈了" << endl;}void Destroy(){cout << "销毁栈" << endl;}int stackSize(){return size;}
private:int* a;int size;int capacity;
};

对于protect,这里不做详解,其与private的区别要在后续才能体现。


类域

类是单独享有一个域的,所以类与类之间可以有同名函数与变量,如下:

class stack
{
public:void Init(){cout << "初始化栈" << endl;}void Push(int x){cout << x << "被压栈了" << endl;}void Destroy(){cout << "销毁栈" << endl;}int stackSize(){return size;}
private:int* a;int size;int capacity;
};class List
{
public:void Init(){cout << "初始化顺序表" << endl;}void Push(int x){cout << x << "顺序表尾插" << endl;}void Destroy(){cout << "销毁顺序表" << endl;}private:int* a;int size;
};

以上代码中,定义了一个顺序表List,一个栈stack,两者都有InitPushDestroyasize。但是两者并不冲突,因为在不同的类域中。


实例化

类是对对象进行描述的,是一个模型一样的东西,限定了类有哪些成员,定义出一个类并没有分配实际的内存空间来存储它。

可以理解为,类就是一个建筑图纸,其规定了一个建筑有哪些房间,房间大小,尺寸等等。但是图纸是不可以住人的,也就是说还不是一个可以使用的屋子,此时就需要实例化,根据图纸把屋子建出来。
在这里插入图片描述
比如我们上述的栈的类,将其实例化就是:

int main()
{stack s1;stack s2;stack s3;stack s4;return 0;
}

这里我们进行了四次实例化,s1s2s3s4是四个不同的实例,不过我们一般将其称为对象。这四个对象就相当于根据图纸造出来的屋子,它们的结构完全一致,只是可能经过使用后数据会不同。可以理解为不同装修方式会对房屋的内部造成不同的影响,但是房屋的结构依然是一致的。


对象模型

我们先尝试检测一个对象的大小:

class stack
{
public:void Init(){cout << "初始化栈" << endl;}void Push(int x){cout << x << "被压栈了" << endl;}void Destroy(){cout << "销毁栈" << endl;}int stackSize(){return size;}
private:int* a;int size;int capacity;
};int main()
{cout << sizeof(stack) << endl;//输出16return 0;
}

如果你结构体的位段学的好的话,你会发现,其实结构体中只有asizecapacity三个成员,大小也是16个字节。
也就是说:类中的函数没有占用类的空间

其机制为:类的成员变量放在对象本身的空间中,而函数会被放在一个公共代码段,因为函数是一致的。
在这里插入图片描述
所以计算类的大小时,只需要通过结构体的位段,计算成员变量的大小。

除此之外:如果一个类是空类,或者只有成员函数,那么编译器依然会为其分配一个字节的空间


this指针

讲清楚了对象模型后,我们来想一个问题:既然大家都是用的同一个函数,那么这个被调用的函数怎么知道是谁调用的?

比如这样:

class myclass
{
public:void Init(int x, int y, int z){_x = x;_y = y;_z = z;}void Add(){cout << _x + _y + _z << endl;}private:int _x;int _y;int _z;
};int main()
{myclass c1;myclass c2;c1.Init(1, 2, 3);c2.Init(4, 5, 6);c1.Add();c2.Add();return 0;
}

创建了两个myclass类的对象c1c2c1初始化三个成员为1,2,3;c2初始化三个成员为4,5,6。
调用Add函数时,对于Add函数来说,它是如何知道要完成1+2+3还是4+5+6?

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

也就是说,我们在调用类的函数时,函数会偷偷传递一个参数this指针,它指向了成员的地址,这样就可以知道是谁调用了这个函数。

this指针有以下特性:

  1. this指针被const修饰了,函数内部是不允许修改this指针的指向的。
  2. this指针在函数内部是允许使用的

比如我们可以在类中添加一个函数:

void tellMeThis()
{cout << this << endl;
}

这个函数会输出一个隐藏的变量this,我们可以访问this指针。

但是如果我们想在函数内部修改this:

void changeThis()
{this = NULL;
}

这就是非法的了。


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

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

相关文章

腾讯云建站教程-从注册域名到部署网站

腾讯云怎么建站&#xff1f;使用腾讯云搭建网站有三种方式&#xff0c;可以直接购买腾讯云建站服务如网站建设和CloudPages&#xff0c;也可以购买腾讯云服务器&#xff0c;然后使用开源程序搭建网站。腾讯云百科txybk.com分享腾讯云建站教程&#xff1a; 1、网站建设&#xf…

寒假每日一题-小苹果

小 Y 的桌子上放着 n 个苹果从左到右排成一列&#xff0c;编号为从 1 到 n。 小苞是小 Y的好朋友&#xff0c;每天她都会从中拿走一些苹果。 每天在拿的时候&#xff0c;小苞都是从左侧第 1个苹果开始、每隔 2 个苹果拿走 1个苹果。 随后小苞会将剩下的苹果按原先的顺序重新…

403和401状态码之间的区别以及使用场景

403 Forbidden和401 Unauthorized是HTTP状态码&#xff0c;用于表示客户端请求失败的不同情况。它们之间的区别和使用场景如下&#xff1a; 401 Unauthorized&#xff08;未授权&#xff09; 定义&#xff1a;表示请求需要身份验证&#xff0c;但客户端未提供有效的凭据&…

【Leetcode】接雨水(双指针、单调栈)

目录 &#x1f4a1;题目描述 &#x1f4a1;双指针解法 &#x1f4a1;单调栈解法 &#x1f4a1;题目描述 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 提示&#xff1a; n height.length1 < n…

010-新手如何建立一个属于自己的图像处理FPGA/ZYNQ框架(自己的用着才舒服,内容非常全面!)

文章目录 前言一、图像处理框架二、图像采集输入1.常用视频流格式&#xff1a;Rgb565/Bayer1.RGB565数据流格式2.Bayer阵列数据流格式 2.图像预处理&#xff1a;时钟域同步/去马赛克/色彩空间转换/滤波1.时钟域同步2.图像去马赛克化3.色彩空间转换4.滤波 三、图像算法处理1.图像…

【后端】深入浅出Node.js

文章目录 1.Node简介1.1 诞生历程1.2 阻塞IO和异步IO 【后端目录贴】 1.Node简介 1.1 诞生历程 Node特点 事件驱动、非阻塞I/O node和chrome浏览器区别 除了HTML、WebKit和显卡这些UI相关技术没有支持外&#xff0c;Node结构与Chrome十分相似&#xff0c;他们都是基于事件驱动…

Vue 组件通信方式

✨ 专栏介绍 在当今Web开发领域中&#xff0c;构建交互性强、可复用且易于维护的用户界面是至关重要的。而Vue.js作为一款现代化且流行的JavaScript框架&#xff0c;正是为了满足这些需求而诞生。它采用了MVVM架构模式&#xff0c;并通过数据驱动和组件化的方式&#xff0c;使…

AI大模型开发架构设计(1)——LLM大模型Agent剖析和应用案例实战

文章目录 LLM大模型Agent剖析和应用案例实战1 从 LLM 大模型到智能体演进技术语言模型是什么&#xff1f;大语音模型是什么&#xff1f;大语言模型日新月异LLM大模型存在局限性LLM Agent来势凶凶LLM Agent增长迅猛LLM Agent是什么&#xff1f; 2 LLM Agent 架构深度剖析规划能力…

关于VMDK、VHDX和VHD的知识,看这篇文章就差不多了

VMDK、VHDX和VHD是虚拟驱动器的文件格式。它们是唯一的,与其他文件不同,你不能只双击它们来打开文件。以下是关于如何在Windows 11/10中打开VMDK、VHDX、VHD文件的完整指南。 什么是VMDK、VHDX和VHD文件 VHD(Virtual Hard Disk)是一种用于表示虚拟驱动器的文件格式。它与系…

Security Identifiers

SecurityIdentifiers SID (安全标识符) 是用于标识 受托人的可变长度的唯一值。 每个帐户都有一个由机构&#xff08;如 Windows 域控制器&#xff09;颁发的唯一 SID&#xff0c;并存储在安全数据库中。 每次用户登录时&#xff0c;系统都会从数据库中检索该用户的 SID&#…

OpenCV实战——OpenCV.js介绍

OpenCV实战——OpenCV.js介绍 0. 前言1. OpenCV.js 简介2. 网页编写3. 调用 OpenCV.js 库4. 完整代码相关链接 0. 前言 本节介绍如何使用 JavaScript 通过 OpenCV 开发计算机视觉算法。在 OpenCV.js 之前&#xff0c;如果想要在 Web 上执行一些计算机视觉任务&#xff0c;必须…

线性代数:矩阵运算(加减、数乘、乘法、幂、除、转置)

目录 加减 数乘 矩阵与矩阵相乘 矩阵的幂 矩阵转置 方阵的行列式 方阵的行列式&#xff0c;证明&#xff1a;|AB| |A| |B| 加减 数乘 矩阵与矩阵相乘 矩阵的幂 矩阵转置 方阵的行列式 方阵的行列式&#xff0c;证明&#xff1a;|AB| |A| |B|

核密度曲线(python

目录 1.代码&#xff1a;2.效果&#xff1a;小结&#xff1a; 1.代码&#xff1a; import pandas as pd import matplotlib.pyplot as plt # 读入数据 file r123.xlsx sheet Sheet2 col S213 # 标题名称 title col 供订比曲线 xlabel 供订比 # 横轴显示范围 xleft 0 xr…

解决 conda新建虚拟环境只有一个conda-meta文件&conda新建虚拟环境不干净

像以前一样通过conda 新建虚拟环境时发现环境一团糟&#xff0c;首先新建虚拟环境 conda create -n newenv这时候activate newenv&#xff0c;通过pip list&#xff0c;会发现有很多很多的包&#xff0c;都是我在其他环境用到的。但诡异的是&#xff0c;来到anaconda下env的目…

加固密码安全:保护您的个人信息

一、引言 在数字化时代&#xff0c;密码安全是保护个人信息和数据的重要环节。然而&#xff0c;许多人在创建和管理密码时存在一些常见的安全漏洞&#xff0c;如使用弱密码、重复使用密码等。本文将详细介绍密码安全的重要性&#xff0c;并提供一些有效的方法和技巧&#xff0…

【嘉立创EDA-PCB设计指南】4.模块化布局

前言&#xff1a;本文对本专栏中的【嘉立创EDA-PCB设计指南】前面绘制的原理图进行模块化布局&#xff0c;首先进行预布局&#xff08;将每个模块放一起&#xff09;&#xff0c;然后进行精细化布局&#xff08;按照原理图来精细化布局&#xff09;。 目录 模块化预布局 模块…

【AI理论知识】EM算法

基本定义 期望最大化算法&#xff08;Expectation-Maximization&#xff0c;EM算法&#xff09;是一种用于估计包含潜在变量的概率模型参数的迭代优化算法。EM算法的主要目标是在存在未观测数据或缺失数据的情况下&#xff0c;通过迭代地进行期望步骤&#xff08;E步&#xff…

软件工程应用题汇总

绘制数据流图(L0/L1/L2) DFD/L0&#xff08;基本系统模型&#xff09; 只包含源点终点和一个处理(XXX系统) DFD/L1&#xff08;功能级数据流图&#xff09;在L0基础上进一步划分处理(XXX系统) 个人理解 DFD/L2&#xff08;在L1基础上进一步分解后的数据流图&#xff09; 数据…

2023江苏职教高考计算机技能考试--改错题解析

/*----------- 【程序改错】 ------------- 题目&#xff1a;函数int pd(int x,int y)功能&#xff0c;判断 给定的两个正整数&#xff0c;是否由相同位数的相同 数字组成。若是&#xff0c;则返回1&#xff0c;否则返回0. 程序运行输出结果为&#xff1a;409--904:符合条件27-…

公司搭建网站使用腾讯云如何建站?

腾讯云怎么建站&#xff1f;使用腾讯云搭建网站有三种方式&#xff0c;可以直接购买腾讯云建站服务如网站建设和CloudPages&#xff0c;也可以购买腾讯云服务器&#xff0c;然后使用开源程序搭建网站。腾讯云百科txybk.com分享腾讯云建站教程&#xff1a; 1、网站建设&#xf…