【C++】类和对象(上)

【C++】类和对象

  • 前言
  • 遗漏的部分
    • 内联函数
      • 使用注意
    • 语法糖
      • auto
      • 循环(:)
  • 正篇:面向对象(上)
    • 面向对象的思路
    • 类和对象
      • stuct的升级
      • 对象
      • class
      • 封装(private protect public)
      • 定义和声明分离
      • this指针

前言

这个篇章算是博主学习的一个里程碑
终于踏上了面向对象的语言的编程模式的正式学习
这里博主会写三篇博客来讲解类和对象。

遗漏的部分

这里是没有讲完的C++的优化的小部分,因为篇幅很小,所以选择在这里补上

内联函数

众所周知,程序的运行就是不停的调用和执行函数
从main函数开始,到return 0 视为程序的运行的结束

按照之前讲的函数栈帧的知识,当调用函数时,就会在栈上申请空间,创建变量,执行代码,执行结束后,就销毁栈帧。

但是当我们遇到一个需要被频繁调用的函数时,就会花费大量时间在栈帧的创建和销毁上,十分影响效率。

在C语言中,如果被频繁调用的代码我们会使用宏定义去进行优化

原理就是define的代码会将代码直接进行展开,避免了栈的申请和销毁空间的时间花费。

而在C++中,祖师爷特意进行了一个优化功能
那就是inline

相比于宏定义,内联函数更好控制,并且可以进行调试


 
inline int Add(int x, int y)
{
   return x + y;
}

加了inline后,就会进行类似于C的宏展开效果

但是inline并不能直接将函数直接变为内联函数,只是向编译器的一个建议,最后还是要编译器决定

这里就要谈谈内联函数的局限了

当函数代码量过于大时,对函数代码进行进行展开后

在这里插入图片描述
从这里可以看出内联函数的局限
只有代码体量小并且调用频繁的代码才适合inline展开。

使用注意

1.inline虽然相比于宏定义能调试,但是只能在debug下进行调试,在debug下还是以普通代码进行运行(这样可以进行调试),当release下,才进行代码展开,以内联函数进行运行,但release下也就不能进行调试了

2.inline关键字只是对编译器的建议,真正是否将函数进行代码展开还是取决于编译器,防止用户瞎用

  1. 内联函数不能定义和声明分离,最好全写在头文件中
    因为内联函数使用时不需要像其他函数一样生成call去调用函数,而是直接将代码展开
    而声明和定义分离是通过地址去调用实现的,内联函数没有地址(因为展开了)所以不能调用,所以不能定义和声明分离

语法糖

auto

auto算是C++更新的一个语法糖。

auto会根据右边的表达式决定左边的类型
例:


Int x=10;
auto a=&x; //——auto会自动识别类型

但是auto* b=x是错误的
因为auto* b固定为指针类型,接下来就是判断是什么类型的指针。

并且引用也是可以的

int x=10;
auto & c =x;

这样是创建了一个指向x的引用。

现在可能还看不出来这个auto有多方便,但是以后会很方便,但是博主现在也是才疏学浅,所以这里只能小小提一下

循环(:)

int arr[3] = { 1,2,3 };
for (int c : arr)

这里的:,代表的意思是:
将arr的每个元素,都遍历赋值给c

所以这里我们可以打印C,来做到打印数组的值

int arr[3] = { 1,2,3 };
	for (int& c : arr)
	{
		cout << c << endl;
	}

在这里插入图片描述

那如果我们想改变数组中的值呢?

这里我们只要给c加一个引用就可以了。

	int arr[3] = { 1,2,3 };
	for (int& c : arr)
	{
		c++;
	}
	for (int i = 0; i < 3; i++)
		cout << arr[i] << endl;

在这里插入图片描述
for (int& c : arr)

这里就代表将arr的数据都赋值给引用变量C
而C为arr元素的引用
所以改变C就会改变arr的元素。

正篇:面向对象(上)

面向对象的思路

大家都知道以前学过的C是面向过程的语言。

而像现在耳熟能详的C++和java等都称作面向对象的语言

面向对象和面向过程是两种不同的开发思路,可以认为面向对象是比面向过程更高级的开发方式

就比如要送一顿外卖

在面向过程看来:
就要分解成
接单 买食材 做菜 包装 取餐 送菜 结束订单

这里的送外卖是我们要达成的目标
而送外卖的每一个过程都被细分出来,都进行分别的独立实现

那现在来看看面向对象:

顾名思义就是将送外卖的方法通过细分成类

商家 外卖平台 外卖员 顾客

这里送外卖被细分成了四类
在面向过程中被细分的送外卖的过程部分,都分别分配到每个类中去实现

这里看起来可能没有啥高级的,但是结合生活来说
当不同的过程有专门的人或机构来执行时,效率和成本都能大大减少

在程序开发中也是有很多好处的,这需要在不停的学习中去感受,这里凭空而谈的话也是十分抽象,不易理解。

类和对象

说到面向对象,那肯定是要先学习类和对象了

前面我们知道,类是具有一定功能集合体

而要实现功能,就需要两个要素:
1.变量
2.函数
这两个可以说是所有程序都需要的最基本的两个要素了

所以说我们的类,需要具有函数和变量
所以类包括
1.成员变量
2.成员函数

所以类可以看作是成员变量和成员函数的集合体

看到这里有没有大家有没有想到C语言中的老朋友

stuct的升级

struct
它在C语言中是结构体(自定义变量)
可以包括成员变量,但是没有成员函数

这个时候祖师爷就把他升级为了类

让他可以包括成员函数了

struct A
{
	int add()
	{
		return _x + _y;
	}

	int _x;
	int _y;
};

这里就是我们创建了一个A类
A类里面包括了
成员函数:add
成员变量: _x _y

对象

那我们知道类了以后,那什么是对象呢?

这里可以生动的表示理解为:图纸和房子的关系

比如说,类为图纸,以类为创建的变量就是对象。

例:
在这里插入图片描述
这里创建了一个z类
在main函数中,用Z a,就是说以Z类为图纸,创建了一个Z类的变量a
这个时候a就是对象。

这里我们调用类中的a的对象的函数的时候用的是像结构体以前用的(.)操作符
**为什么不用类的::操作符?**这后面会有解释。

同时类也是单独的一个域,里面的成员函数和成员变量在访问时都需要单独的访问符号

同时也有一个问题出来了,以前计算struct的大小,只需要计算变量即可
但是现在成为类后有了成员函数,那struct的大小该怎么计算

直接告诉结果吧。

类的计算和原本的struct计算方式一样,只需要注意内存对齐+计算成员变量即可,因为成员函数存储在公共的代码区。
那如果创建了一个空类呢?
在这里插入图片描述
在这里插入图片描述

这里看到空类和只有成员函数的类字节都为1
这里留一个字节是系统知道用户创建了一个类,留了个空间
同时也证明了,成员函数不占空间,而是在公共的代码区。

这里放上以前的struct计算方法(也是以前写的博客)以前struct大小计算

将struct升级成了类后,可能是祖师爷觉得不够用,选择创建了一个单独的类

class

class z//创建了一个类型z
{
	int add(int x, int y)
	{
		_x = x;
		_y = y;
		return _x + _y;
	}
	int _x;
	int _y;
};

这样创建了一个类型z后,使用时会发现有问题

在这里插入图片描述
在这里插入图片描述

创建了一个类后发现却无法调用成员变量和成员函数

这里报错时显示的时显示的是无法访问

这里就要扯到面向对象三大特点的之一的封装了

封装(private protect public)

学过C的人都知道,当我们在使用和写函数时,过于自由

就比如当我们写了一个栈时,其中的capacity和date等成员变量
就会被人直接拿来修改和调用
Stack.capacity=0,当capacity被改变后,Stack会乱套的所
以为了防止以上缺德的行为,就在类中设置了权限

总共有三种权限情况:
private protect public

public:允许在类域外进行调用
private和protect(主要区别在继承):不允许类域外的进行调用,但是类域内的成员函数还是能随便调用

从我们上面的错误可以知道
在class中我们没有设置权限的时候,默认为private状态,不允许类域外进行调用
在struct却可以进行调用,因为struct默认成员变量和函数都是public(因为要兼容C,C中的struct为默认公开状态)

那怎么样可以改变class中的权限呢?

在这里插入图片描述

这里就可以发现调用函数成功了。

但是这和我们C语言中的高度自由有什么区别呢?
在这里插入图片描述
又可以对类中的成员变量进行随意改变了

所以一般来讲,将接口(函数)进行public
将成员变量进行private,来防止别的用户对成员变量进行随便改变

在这里插入图片描述
这里就可以发现不能随意在类域外对成员变量进行改变了。

定义和声明分离

这个也是C中的经典玩法了
但是在C++中,类成为了单独的一个域
众所周知,不同的域中的变量和函数可以重名,所以不能像以前一样直接对函数进行定义。
这里拿我们以后会将到的运算符重载演示一下:

bool operator<(const Date& d);//声明

//加了类域限定符
bool Date::operator<(const Date& d)
{
	if (_year < d._year)
		return true;
	else if (_year == d._year && _month < d._month)
		return true;
	else if (_year == d._year && _month == d._month && _day < d._day)
		return true;
	return false;
}

这里我们就能清楚地看到,进行函数的定义的时候需要加上特定的类域限定符。

this指针

还记得留了两个坑吗

1:为什么调用类的函数时,是用对象去调用,而不是用域限制符去调用?
2: 在这里插入图片描述

我们知道类的函数在公共区域,就是说对象a1和a2调用的函数一样
并且没有传参数,为什么print的结果却是不一样的?

这里就要牵扯到this指针了。

实际上它的调用是这样的。

print(a1)
print(a2)

他是进行传参的,只不过这个时编译器替我们做了而已,相当于隐形传参

并且在函数中是可以进行调用的

void print()
	{
		this->_x += 10;//this就是代表调用的对象的指针
		cout << _x << endl;
	}

在这里插入图片描述

但同时,编译器不允许我们自己去进行传参

所以现在的两个问题都迎刃而解了。

1.为什么不能用域限定操作符来进行访问

z::print();

因为这样就和对象没有关系了,无法传输对象的指针

2.为什么a1和a2没有传参,调用的函数一样,打印结果却不同

看起来没有传参,其实在调用对象的函数的时候,就已经进行隐藏传入了对象的指针,所以才能区分a1和a2的_x

那这样还有一个问题了?

那这个this指针是存储在哪的?

毫无疑问,是存放在栈区中的,当函数调用结束的时候就会进行销毁。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Vue3通透教程【十二】TS类型声明优势

文章目录 &#x1f31f; 写在前面&#x1f31f; 上篇文章解惑&#x1f31f; JS函数中的隐患&#x1f31f; 函数中的类型&#x1f31f; 写在最后 &#x1f31f; 写在前面 专栏介绍&#xff1a; 凉哥作为 Vue 的忠实 粉丝输出过大量的 Vue 文章&#xff0c;应粉丝要求开始更新 V…

2023-5-19-Debug和Release到底有多少不同?

&#x1f37f;*★,*:.☆(&#xffe3;▽&#xffe3;)/$:*.★* &#x1f37f; &#x1f4a5;&#x1f4a5;&#x1f4a5;欢迎来到&#x1f91e;汤姆&#x1f91e;的csdn博文&#x1f4a5;&#x1f4a5;&#x1f4a5; &#x1f49f;&#x1f49f;喜欢的朋友可以关注一下&#xf…

垃圾站养殖场除臭杀菌解决方案

养殖场和垃圾站都会产生大量的有机废气和垃圾&#xff0c;这些废气和垃圾会产生难闻的臭味&#xff0c;影响周围环境和居民健康。这些地方又是病菌和细菌的滋生地&#xff0c;这些细菌和病菌会对人类和动物的健康造成威胁。除臭杀菌系统可以杀灭这些细菌和病菌&#xff0c;也可…

【Java|golang】1080. 根到叶路径上的不足节点--dfs

给你二叉树的根节点 root 和一个整数 limit &#xff0c;请你同时删除树中所有 不足节点 &#xff0c;并返回最终二叉树的根节点。 假如通过节点 node 的每种可能的 “根-叶” 路径上值的总和全都小于给定的 limit&#xff0c;则该节点被称之为 不足节点 &#xff0c;需要被删…

回溯法【2-5】

假设一个推销员问题由下图定义&#xff0c;用回溯法求解 从1号结点出发的相应最短巡回路径&#xff08;每个顶点刚好到达一次&#xff09;。若用bestL表示搜索过程中产生的当前最优解&#xff0c;剪枝函数 L 设计为&#xff1a; L 已走过的路径长度 当前结点相关的最短边 所…

10:00进去,10:05就出来了,这问的也太变态了···

从外包出来&#xff0c;没想到死在另一家厂子了。 自从加入这家公司&#xff0c;每天都在加班&#xff0c;钱倒是给的不少&#xff0c;所以也就忍了。没想到5月一纸通知&#xff0c;所有人不许加班&#xff0c;薪资直降30%&#xff0c;顿时有吃不起饭的赶脚。 好在有个兄弟内推…

【Win32】资源文件(对话框),逆向对话框回调函数,消息断点(附带恶意软件源码)

之前在学习windows编程的时候已经写过对话框的创建了&#xff0c;其中包括了对话框的分类&#xff0c;原理等等&#xff0c;大家可以去看一下&#xff1a;【windows编程之对话框】对话框原理&#xff0c;对话框的创建。原理今天就讲的不是很多了&#xff0c;直接给大家给出步骤…

《Go专家编程(第2版)》书评

首先感谢官方的肯定&#xff0c;让我在【图书活动第四期】的活动中获得了《Go专家编程(第2版)》这本书&#xff0c;以下是从我的观点对这本书的书评 文章目录 前言书籍部分读者评价总结 前言 很高兴有机会写一篇关于《Go专家编程&#xff08;第2版&#xff09;》的书评。大致读…

APIO2023 游记

GDOI 和 GDKOI 的游记都咕咕咕了&#xff0c;而且都炸了&#xff0c;APIO 的游记提前发&#xff0c;就是要破釜沉舟。 我是线上选手。 Day -7 我们原题检测&#xff0c;阿克了&#xff0c;毕竟是原题&#xff0c;虽然有两道博弈论黑题确实挺毒瘤的。 教练让我做 APIO2012 的…

产品经理必读丨如何找准产品定位?

我们都知道&#xff0c;当一款新产品开始立项之前&#xff0c;势必需要经过谨慎的市场调研才能整合资源启动新的项目&#xff0c;但除此之外&#xff0c;作为产品经理还需要做好一件关键的事情——找准产品在市场中的定位。 什么是产品定位 百度百科对产品定位的解释是非常准确…

【STM32】基础知识 第十六课 窗口看门狗 WWDG 深入浅出

【STM32】基础知识 第十六课 窗口看门狗 WWDG 深入浅出 概述窗口看门狗 (WWDG)WWDG_SR 状态寄存器WWDG 配置与使用使用 WWDG 进行故障检测案例 概述 在嵌入式开发中, 可靠性和稳定性是至关重要的. 这就是为什么许多单片机, 比如 STM32, 提供了窗口看门狗 (Window Watchdog, WW…

k8s部署dashboard

1.查看k8s集群版本 kubectl version 2.在github中查看k8s对应的ui版本 Releases kubernetes/dashboard GitHub 3.下载对应版本的dashboard yaml文件 wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml 4.更改yaml文件配置 …

HTB-Agile

HTB-Agile 信息收集80端口漫长的兔子洞之旅 立足www-data -> corumcorum -> edwardsedwards -> root 信息收集 80端口 漫长的兔子洞之旅 我注意到系统为我分配了一个session&#xff0c;是以eyj开头的。 拿去jwt.io看看。 额&#xff0c;可能后面会用先留在这&#…

多线程-程序、进程、线程与并行、并发的概念

多线程 本章要学习的内容&#xff1a; 专题1&#xff1a;相关概念的理解专题2&#xff1a;多线程创建方式一&#xff1a;继承Thread类专题3&#xff1a;多线程创建方式二&#xff1a;实现Runnable接口专题4&#xff1a;Thread类的常用方法专题5&#xff1a;多线程的优点、使用…

5月编程排行榜出炉,最佳编程语言是谁?

技术的发展日新月异&#xff0c;作为开发者&#xff0c;应该时刻关注这些变化&#xff0c;不断学习才能跟上时代步伐。 编程语言层出不穷&#xff0c;关于“ 最佳编程语言 ”的争论也从未停止&#xff0c;网友们各抒己见...... 网友A&#xff1a; 人生苦短&#xff0c;我选Pyt…

软件测试工程师如何提高自己的竞争力?

案例一来自我们的资深功能测试工程师招聘。当时&#xff0c;有一位拥有近 9 年测试经验的资深测试候选人&#xff0c;我对他的简历还是比较满意的&#xff0c;所以就安排了面谈。但是&#xff0c;在聊的过程中我很快发现&#xff0c;这位候选人绝大多数的测试经验积累都“强”绑…

利用 DynamoDB 和 S3 结合 gzip 压缩,最大化存储玩家数据

前言 一些传统游戏架构中&#xff0c;采用 MySQL 存储玩家存档数据&#xff0c;利用分库分表分散单库单表的存储和性能压力&#xff0c;从而达到支持更多玩家的目的。随着数据量增长&#xff0c;数据表中 varchar 类型已经无法满足游戏中单字段的存储需求&#xff0c;而 blob …

去哪儿酒店数据下载

字段内容包含&#xff1a; id int(11) NOT NULL AUTO_INCREMENT, hotelid varchar(50) DEFAULT NULL, url varchar(200) DEFAULT NULL, hotelname2 varchar(100) DEFAULT NULL, name varchar(100) DEFAULT NULL, province varchar(50) DEFAULT NULL, d…

RabbitMQ集群安装

RabbitMQ集群安装 1.前言 OS: CentOS Linux release 7.9.2009 (Core) 机器: IPnodecpu内存存储10.106.1.241max-rabbitmg-018 核16 G100 G10.106.1.242max-rabbitmg-028 核16 G100 G10.106.1.243max-rabbitmg-038 核16 G100 G 因为操作系统版本是 centos7&#xff0c;所以…

跟着chatGPT学习:kubernetes中的Reflector、list-watcher、informer等概念

以下是我跟chatGPT学习kubernetes中Reflector、list-watcher、informer等的概念的过程 不敢保证chatGPT回答的百分之百准确。但是&#xff0c;确实帮助我了我理解&#xff01; 最终学习的是下面的图&#xff0c; 1、在kubernetes中Reflector原理&#xff1f; 在Kubernetes…