c++--类(上)

devtools/2024/10/15 18:30:05/

C++之类(上)

  • 一、类的定义
    • 1.1 类定义格式
    • 1.2 访问限定符
    • 1.3 类域
  • 二、实例化
    • 2.1 实例化的概念
    • 2.2 对象大小
  • 三、this指针

一、类的定义

1.1 类定义格式

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

class stack
{int*arr;int size;int capacity;//成员变量void Push(int x);int Top();void Pop();//成员函数
};

这个就是一个栈的类,它与结构体不同,类是变量与函数不分离。

2、为了区分成员变量,⼀般习惯上成员变量会加⼀个特殊标识,如成员变量前⾯或者后⾯加_ 或者 m开头。

class direction
{
public:void Init(int left, int right, int up, int down){_left = left;_right = right;_up = up;_down = down;}
private://在这里有两种方式可以用来区分//1、在成员变量前加_//2、用this指针例如(this->left=left)int _left;int _right;int _up;int _down;
};

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

struct stack
{int*arr;int size;int capacity;//成员变量void Push(int x);int Top();void Pop();//成员函数
};

这个也是可以的。

4、定义在类⾯的成员函数默认为inline。如果我们不想在类里写我们的函数体,就得用::域作用限定符。

class direction
{
public:void Init(int left, int right, int up, int down);
private://在这里有两种方式可以用来区分//1、在成员变量前加_//2、用this指针例如(this->left=left)int _left;int _right;int _up;int _down;
};
void direction::Init(int left, int right, int up, int down)
{_left = left;_right = right;_up = up;_down = down;
}

1.2 访问限定符

在这里插入图片描述
1、C++⼀种实现封装的⽅式,⽤类将对象的属性与⽅法结合在⼀块,让对象更加完善,通过访问权限选择性的将其接⼝提供给外部的⽤户使⽤。这里的接口指的就是函数。

2、public修饰的成员在类外可以直接被访问protected和private修饰的成员在类外不能直接被访问,protected和private是⼀样的,在继承章节才会体现它俩的不同。
在这里插入图片描述
大家可以看到size可以轻易的访问,而Top就不能被访问。

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

class stack
{
public:int*arr;int size;int capacity;//成员变量//public的范围到private之前
private:void Push(int x);int Top();void Pop();//成员函数//后面已经没有访问限定符了,那么private的范围到“}”之前
};

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

5、最后访问限定符可以多次出现,但实际使用一般不这样写。

1.3 类域

类定义了⼀个新的作⽤域,类的所有成员都在类的作⽤域中,在类体外定义成员时,需要使⽤ :: 作⽤域操作符指明成员属于哪个类域。
在这里插入图片描述
特别是这种两个类成员函数名字一样的,一定要指明类域。

二、实例化

2.1 实例化的概念

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

class direction
{
public:void Init(int left, int right, int up, int down);
private://在这里有两种方式可以用来区分//1、在成员变量前加_//2、用this指针例如(this->left=left)int _left;int _right;int _up;int _down;
};
void direction::Init(int left, int right, int up, int down)
{_left = left;_right = right;_up = up;_down = down;
}
int main()
{direction d1, d2;return 0;
}

在这里我们就实例化了两个对象d1,d2。

2、类是对象进⾏⼀种抽象描述,是⼀个模型⼀样的东西,限定了类有哪些成员变量,这些成员变量只是声明,没有分配空间,⽤类实例化出对象时,才会分配空间。
什么意思呢?就是我们定义的类只是一个声明,当我们创建对象,例如上面的d1,d2时才会分配空间。

3、⼀个类可以实例化出多个对象,实例化出的对象 占⽤实际的物理空间,存储类成员变量。
在这里插入图片描述

2.2 对象大小

类实例化出的每个对象,都有独⽴的数据空间,所以对象中肯定包含成员变量,那么成员函数是否包含呢?⾸先函数被编译后是⼀段指令,对象中没办法存储,这些指令存储在⼀个单独的区域(代码段),那么对象中⾮要存储的话,只能是成员函数的指针。
我们只需要记住在算对象大小的时候,不需要计算成员函数,只计算成员变量。
那现在问题来了,要是我们的类里什么都没有,但我们用它实例化了对象,那实例化后的对象的大小是多少啊?
在这里插入图片描述
这⾥给1字节,纯粹是为了占位标识对象存在。

其次我们要算对象的大小我们只需要计算成员变量的大小,其算法与struct的算法一致都是符合内存对齐原则:
在这里插入图片描述
那大家有没有想过为什么要内存对齐啊?
在这里插入图片描述

三、this指针

首先我们先看一个代码:

class direction
{
public:void Init(int up, int down, int left, int right){_left = left;_right = right;_up = up;_down = down;}
public:int _left;int _right;int _up;int _down;
};
int main()
{direction d1, d2;d1.Init(0, 1, 2, 3);d2.Init(3, 2, 1, 0);cout << d1._up << ' ' << d1._down << ' ' << d1._left << ' ' << d1._right << endl;cout << d2._up << ' ' << d2._down << ' ' << d2._left << ' ' << d2._right << endl;return 0;
}

为什么这里是同一个函数,打印的确实一样的呢?这里就引入了this指针,this指针通常都是隐含的

那我们将它恢复回原来的样子:

class direction
{
public://void Init(data*const this,int up,int down......)void Init(int up, int down, int left, int right){this->_left = left;this->_right = right;this->_up = up;this->_down = down;}
public:int _left;int _right;int _up;int _down;
};
int main()
{direction d1, d2;d1.Init(0, 1, 2, 3);//d1.Init(&d1, 0, 1, 2, 3);d2.Init(3, 2, 1, 0);//d2.Init(data* const this,3,2,1,0);//d2.Init(&d2, 3, 2, 1, 0);cout << d1._up << ' ' << d1._down << ' ' << d1._left << ' ' << d1._right << endl;cout << d2._up << ' ' << d2._down << ' ' << d2._left << ' ' << d2._right << endl;return 0;
}

需要注意的是:C++规定不能在实参和形参的位置显⽰的写this指针(编译时编译器会处理),但是可以在函数体内显⽰使⽤this指针。

最后我们需要知道this指针存在于哪个区域,是堆、栈,还是常量区还是对象里?

我们要知道this指针是作为形参传递的对不对,形参存储于栈里,所以在这里栈比较合适,但是由于c++里经常使用this指针,所以有些编译器会将其放入寄存器,但是在做题过程中我们选栈。

这两个题目有助于我们理解this指针,大家可以简单的看下

1、问它运行结果是什么?

#include<iostream>
using namespace std;
class A
{
public:void Print(){cout << "A::Print()" << endl;}
private:int _a;
};int main()
{A* p = nullptr;p->Print();return 0;
}
//A、编译报错 B、运⾏崩溃 C、正常运⾏

这个题目选择正常运行,虽然这里p是空指针,但我们这里是将它的地址作为参数传递,成员函数不存于类的变量中,我们访问成员函数并没有通过this指针。
在这里插入图片描述

#include<iostream>
using namespace std;
class A
{
public:void Print(){cout << "A::Print()" << endl;cout << _a << endl;}
private:int _a;
};
int main()
{A* p = nullptr;p->Print();return 0;
}//A、编译报错 B、运⾏崩溃 C、正常运⾏

而在这里我们使用了_a这个成员变量,这里解引用了空指针,所以这里运行崩溃。


http://www.ppmy.cn/devtools/97915.html

相关文章

「OC」探索CALayer:基础知识与实用技巧简要介绍

「OC」探索CALayer&#xff1a;基础知识与实用技巧简要介绍 文章目录 「OC」探索CALayer&#xff1a;基础知识与实用技巧简要介绍前言认识CALayerCALayer的相关属性 UIView和CALayer区别联系创建UIView和CALayer的原因 开始创建CALayer视图层级CALayers 和 Sublayersposition与…

CI/CD

目录 1.什么是CI/CD? 2.Gitlab仓库部署 3.部署Jenkins 3.1 使用jenkins拉取代码 3.2 对代码进行编译、打包 4.部署tomcat服务器 1.什么是CI/CD? 通俗来说就是启动一个服务&#xff0c;能够监听代码变化&#xff0c;然后自动执行打包&#xff0c;发布等流程: CICD 是持…

通过Docker部署Synapse服务器

今天我们在阿贝云免费服务器上进行部署测试。阿贝云免费服务器&#xff0c;简直就是IT界的一颗明星&#xff01;1核CPU、1G内存、10G硬盘、5M带宽&#xff0c;简直就是一个不错的免费服务器选择。 首先&#xff0c;让我们简要介绍一下使用到的Docker和Synapse软件。Docker是一…

某系统存在任意账户凭据窃取漏洞

世人都晓神仙好&#xff0c;惟有功名忘不了&#xff01;古今将相今何在&#xff1f;荒冢一堆草没了。 漏洞描述 某系统存在任意账户凭据窃取漏洞&#xff0c;攻击者使用任意账号登录后访问特殊的Url即可获取所有用户的账号和密码 漏洞复现 登录后台(存在访客用户默认账号密…

美股收涨,半导体板块领涨;苹果iPhone出货预测上调

市场概况 在昨夜的交易中&#xff0c;美股三大股指全线收涨。道琼斯工业平均指数上涨1.39%&#xff0c;纳斯达克综合指数上涨2.34%&#xff0c;标准普尔500指数上涨1.61%。值得注意的是&#xff0c;英伟达股票涨幅近4%&#xff0c;推动了科技股的整体表现。美国十年期国债收益…

无人机航拍与ArcGIS融合实战:从地表观测到空间数据可视化的全方位指南!无人机图像拼接数据处理与分析、可视化与制图

目录 第一章 无人机航拍基本流程、航线规划与飞行实践 第二章 无人机图像拼接软件的学习与操作实践 第三章 无人机图像拼接典型案例详解 第四章 无人机图像拼接数据在GIS中的处理与分析 第五章 无人机图像拼接数据在GIS中的可视化与制图 第六章 综合案例:无人机航拍植被动…

华为HCIP证书好考吗?详解HCIP证书考试难易程度及备考策略!

华为认证体系主要分为三个层次&#xff1a;HCIA(Huawei Certified ICT Associate)&#xff0c;HCIP(Huawei Certified ICT Professional)和HCIE(Huawei Certified Internetwork Expert)。作为中级认证&#xff0c;HCIP证书主要面向具备一定技术基础和项目实践能力的专业人士。在…

React+Vis.js(05):vis.js的节点的点击事件

文章目录 需求实现思路抽屉实现完整代码需求 双击节点,弹出右侧的“抽屉”,显示节点的详细信息 实现思路 vis.network提供了一个doubleClick事件,代码如下: network.on(doubleClick, function (properties) {// console.log(nodes);let id = properties