【iOS】事件传递与响应机制

文章目录

  • 前言
  • 事件UIEvent
  • 一、事件传递
    • 遍历顺序
  • 二、手势识别
  • 三、响应机制
      • UIResponder(响应者)
      • 响应者链
  • 四、相关应用
    • 扩大button点击范围
    • 穿透事件
  • 总结


前言

提到响应者链与事件传递,如果看过其他人的博客,经常能看到这经典的三张图
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

本文会对事件的传递与响应机制进行详细的讲解

事件UIEvent

在开讲之前,我们先来理解一下UIEvent
事件指的是 UIEvent : NSObject,它的API文档很简单:

typedef NS_ENUM(NSInteger, UIEventType) {UIEventTypeTouches,UIEventTypeMotion,UIEventTypeRemoteControl,UIEventTypePresses API_AVAILABLE(ios(9.0)),UIEventTypeScroll      API_AVAILABLE(ios(13.4), tvos(13.4)) API_UNAVAILABLE(watchos) = 10,UIEventTypeHover       API_AVAILABLE(ios(13.4), tvos(13.4)) API_UNAVAILABLE(watchos) = 11,UIEventTypeTransform   API_AVAILABLE(ios(13.4), tvos(13.4)) API_UNAVAILABLE(watchos) = 14,
};typedef NS_ENUM(NSInteger, UIEventSubtype) {// available in iPhone OS 3.0UIEventSubtypeNone                              = 0,// for UIEventTypeMotion, available in iPhone OS 3.0UIEventSubtypeMotionShake                       = 1,// for UIEventTypeRemoteControl, available in iOS 4.0UIEventSubtypeRemoteControlPlay                 = 100,UIEventSubtypeRemoteControlPause                = 101,UIEventSubtypeRemoteControlStop                 = 102,UIEventSubtypeRemoteControlTogglePlayPause      = 103,UIEventSubtypeRemoteControlNextTrack            = 104,UIEventSubtypeRemoteControlPreviousTrack        = 105,UIEventSubtypeRemoteControlBeginSeekingBackward = 106,UIEventSubtypeRemoteControlEndSeekingBackward   = 107,UIEventSubtypeRemoteControlBeginSeekingForward  = 108,UIEventSubtypeRemoteControlEndSeekingForward    = 109,
};/// Set of buttons pressed for the current event
/// Raw format of: 1 << (buttonNumber - 1)
/// UIEventButtonMaskPrimary = 1 << 0
typedef NS_OPTIONS(NSInteger, UIEventButtonMask) {UIEventButtonMaskPrimary    = 1 << 0,UIEventButtonMaskSecondary  = 1 << 1
} NS_SWIFT_NAME(UIEvent.ButtonMask) API_AVAILABLE(ios(13.4)) API_UNAVAILABLE(tvos, watchos);/// Convenience initializer for a button mask where `buttonNumber` is a one-based index of the button on the input device
/// .button(1) == .primary
/// .button(2) == .secondary
UIKIT_EXTERN UIEventButtonMask UIEventButtonMaskForButtonNumber(NSInteger buttonNumber) NS_SWIFT_NAME(UIEventButtonMask.button(_:)) API_AVAILABLE(ios(13.4)) API_UNAVAILABLE(tvos, watchos);UIKIT_EXTERN API_AVAILABLE(ios(2.0)) @interface UIEvent : NSObject@property(nonatomic,readonly) UIEventType     type API_AVAILABLE(ios(3.0));
@property(nonatomic,readonly) UIEventSubtype  subtype API_AVAILABLE(ios(3.0));@property(nonatomic,readonly) NSTimeInterval  timestamp;@property (nonatomic, readonly) UIKeyModifierFlags modifierFlags API_AVAILABLE(ios(13.4), tvos(13.4)) API_UNAVAILABLE(watchos);
@property (nonatomic, readonly) UIEventButtonMask buttonMask API_AVAILABLE(ios(13.4)) API_UNAVAILABLE(tvos, watchos);@property(nonatomic, readonly, nullable) NSSet <UITouch *> *allTouches;
- (nullable NSSet <UITouch *> *)touchesForWindow:(UIWindow *)window;
- (nullable NSSet <UITouch *> *)touchesForView:(UIView *)view;
- (nullable NSSet <UITouch *> *)touchesForGestureRecognizer:(UIGestureRecognizer *)gesture API_AVAILABLE(ios(3.2));// An array of auxiliary UITouch’s for the touch events that did not get delivered for a given main touch. This also includes an auxiliary version of the main touch itself.
- (nullable NSArray <UITouch *> *)coalescedTouchesForTouch:(UITouch *)touch API_AVAILABLE(ios(9.0));// An array of auxiliary UITouch’s for touch events that are predicted to occur for a given main touch. These predictions may not exactly match the real behavior of the touch as it moves, so they should be interpreted as an estimate.
- (nullable NSArray <UITouch *> *)predictedTouchesForTouch:(UITouch *)touch API_AVAILABLE(ios(9.0));@endNS_ASSUME_NONNULL_END#else
#import <UIKitCore/UIEvent.h>
#endif

我们以 UIEventType 作为突破口

typedef NS_ENUM(NSInteger, UIEventType) {UIEventTypeTouches,UIEventTypeMotion,UIEventTypeRemoteControl,UIEventTypePresses API_AVAILABLE(ios(9.0)),UIEventTypeScroll      API_AVAILABLE(ios(13.4), tvos(13.4)) API_UNAVAILABLE(watchos) = 10,UIEventTypeHover       API_AVAILABLE(ios(13.4), tvos(13.4)) API_UNAVAILABLE(watchos) = 11,UIEventTypeTransform   API_AVAILABLE(ios(13.4), tvos(13.4)) API_UNAVAILABLE(watchos) = 14,
};

目前iOS主流使用的事件有三种

  • touch events(触摸事件)
  • motion events(运动事件)
  • remote-control events(远程控制事件)
    在这里插入图片描述

我们这里着重讲一下触摸事件

触摸事件就是我们的手指或者苹果的
Pencil(触笔)在屏幕中所引发的互动,比如轻点、长按、滑动等操作,是我们最常接触到的事件类型。触摸事件对象可以包含一个或多个触摸,并且每个触摸由
UITouch 对象表示。当触摸事件发生时,系统会将其沿着线路传递,找到适当的响应者并调用适当的方法,例如
touchedBegan:withEvent:。响应者对象会根据触摸来确定适当的方法。 触摸事件分为以下几类:

手势事件

  • 长按手势(UILongPressGestureRecognizer)
  • 拖动手势(UIPanGestureRecognizer)
  • 捏合手势(UIPinchGestureRecognizer)
  • 响应屏幕边缘手势(UIScreenEdgePanGestureRecognizer)
  • 轻扫手势(UISwipeGestureRecognizer)
  • 旋转手势(UIRotationGestureRecognizer)
  • 点击手势(UITapGestureRecognizer)
  • 自定义手势
  • 点击 button 相关

触摸事件对应的对象为 UITouch,UITouch实际上就对应着我们的手指,有几根手指就有几个UITouch对象

一、事件传递

事件传递机制(Event Handling)
iOS的事件传递系统将触摸和其他事件(如动作、手势)发送到视图层次结构中的适当对象。在事件传递过程中,系统通常从根视图开始查找,并递归向下查找以找到最适合处理该事件的视图。

传递流程

  • 事件的产生
    用户通过手势或是触摸等其他操作与设备交互,生成事件,系统将事件传递给应用的UIApplication实例,以开始事件分发
  • UIApplication事件分发
    UIApplication负责顶层管理所有用户输入事件。
    它将事件传递给当前活动的UIWindow对象,以进一步查找适合的响应者。
  • UIWindow事件分发
    当前活动的UIWindow对象接收事件并通过hitTest:withEvent:方法开始寻找适当的视图
    UIWindow遍历整个视图层次结构,以找到最合适的视图来响应事件。
  • 命中测试(Hit-Testing)
    hitTest:withEvent:寻找第一响应者的核心方法。它通过以下步骤工作:
  1. 检查当前视图的userInteractionEnabled、hiddenalpha属性以确保视图可交互。当视图隐藏属性hidden=NO、交互userInteractionEnabled=YES、透明度alpha>0.01三者同时满足才拥有响应能力。
  2. 调用pointInside:withEvent:,确定触摸点是否在当前视图的边界范围内。
  3. 从后往前遍历子视图,递归调用子视图的hitTest:withEvent:方法。
  4. 如果找到合适的子视图,它将返回该子视图作为第一响应者;否则返回当前视图自身。

我们可以写一个其简单实现实例

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {// 视图不能交互、隐藏或不可见时,直接返回nilif (self.userInteractionEnabled == NO || self.hidden == YES || self.alpha < 0.01) {return nil;}// 判断触摸点是否在当前视图范围内if (![self pointInside:point withEvent:event]) {return nil;}// 从后往前遍历子视图(子视图叠加次序),递归调用for (UIView *subview in [self.subviews reverseObjectEnumerator]) {// 转换坐标到子视图的坐标系CGPoint convertedPoint = [subview convertPoint:point fromView:self];// 递归查找子视图UIView *hitView = [subview hitTest:convertedPoint withEvent:event];if (hitView != nil) {return hitView;}}// 没有合适的子视图时,当前视图自己成为第一响应者return self;
}
  • 第一响应者确定
    如果确定了当前触摸点在当前视图上,同时当前视图没有任何子视图,那么当前视图就成为第一响应者并开始处理触摸事件
    touchesBegan:withEvent:、touchesMoved:withEvent:、touchesEnded:withEvent:、touchesCancelled:withEvent:方法由第一响应者接收并处理,这些都是触摸事件

讲到这里,其实我们的事件传递就已经结束了,事件传递的目的就是为了让我们找到第一响应者

总结一下第一响应者

  1. 能够响应触摸事件
  2. 触摸点在自己身上
  3. 没有任何子视图,或是所有子视图都不在触摸点上

在这里插入图片描述

遍历顺序

我们在上图中看到了在subViews中查找响应者的过程是倒序遍历,这是什么意思呢

也就是我们遍历当前视图的子视图时,首先hitTest:withEvent:方法会被子视图数组中的最后一个元素调用

如何理解这句话呢?简单理解就是会从最后一个添加到当前视图的子视图进行遍历,也就是视图上最上层的子视图是第一个被遍历的,然后再继续去遍历其他子视图,我们来看一个demo:

在这里插入图片描述
可以看到touchView1先被添加到view中,随后再添加touchView2,我们来看一下subViews数组

在这里插入图片描述
可以看到touchView2在数组的尾部,这也就说明了倒序遍历就是从后面添加的视图向前遍历

二、手势识别

找到了合适的View,也就是第一响应者,如果是触摸事件,我们就要去识别是何种手势

使用不同的手势会调用不同次数的事件,这里我们不细讲,只要知道有这么一个过程即可

三、响应机制

在了解响应者链前,我们需要知道什么是响应者

UIResponder(响应者)

在 iOS 中,只有继承于 UIResponder 的对象、或者它本身才能成为响应者。很多常见的对象都可以相应事件,比如 UIApplication 、UIViewController、所有的 UIView(包括 UIWindow)
我们来看一张继承图
请添加图片描述
可以看到UIResponder提供了我们平时最常用的touchesBegan/touchesMoved/touchesEnded方法。此外还有如下几个属性比较重要:

  • isFirstResponder:判断该View是否为第一响应者。
  • canBecomeFirstResponder:判断该View是否可以成为第一响应者。
  • becomeFirstResponder:使该View成为第一响应者。
  • resignFirstResponder:取消View的第一响应者。

如果我们将一个view_A先加在view_B上,然后又加到view_C上,那么view_A.nextResponder指的是view_B

响应者链

找到第一响应者之后并且识别出手势后,我们就要确定由谁来响应这个事件了,如何理解这句话呢?
第一响应者不一定能响应事件,因为他可能并没有实现触摸事件

我们来以一个Demo来理解
在这里插入图片描述
在这里插入图片描述
红色的是V1,蓝色的是V2,V2是第一响应者

我们为我们的V1添加点击事件
在这里插入图片描述

我们点击蓝色区域
在这里插入图片描述
可以看到响应触摸事件的我们的V1,也就是红色区域,这也说明了第一响应者不一定能响应事件

这里需要注意的一点是如果我们要给视图添加触摸事件,一定要新建一个子类View,不能再UIViewC中重写touches实例方法,因为这样事件的响应者就是UIViewC而非你期望中的View,我们也以一个Demo来示范

在VC中重写方法
在这里插入图片描述

在VC中重写方法
在这里插入图片描述
可以看到当我点击空白区域时候响应的是VC,点击蓝色或是红色区域时响应的是V1,这是因为事件的传递是沿响应者链传递的,由此引出我们对响应者链的讨论

响应者链示意图:
在这里插入图片描述
在这里插入图片描述

  • Response Chain,响应链,一般我们称之为响应者链。
  • 在我们的 app 中,所有的视图都是按照一定的结构组织起来的,即树状层次结构,每个 view 都有自己的 superView,包括 controller 的 topmost view(即 controller 的 self.view)。
  • 当一个 view 被 add 到 superView 上的时候,它的 nextResponder 属性就会被指向它的 superView。
  • 当 controller 被初始化的时候,self.view(topmost view) 的 nextResponder 会被指向所在的 controller,而 controller 的 nextResponder 会被指向 self.view的superView。
  • 这样,整个 app 就通过 nextResponder 串成了一条链,这就是我们所说的响应者链。
  • 所以响应者链是一条虚拟的链,并没有一个对象来专门存储这样的一条链,而是通过 UIResponder 的属性串联起来的。
    @property(nonatomic, readonly, nullable) UIResponder *nextResponder;

总结一下响应者链的响应流程
判断当前视图能否响应,再去判断当前视图的nextResponder,如果是VCView,那么nextResponder就是VC
如果不是控制器的 View,上一个响应者就是SuperView

响应的大致的过程 第一响应者 –> super view –> ……–> view controller –> window –>Application

四、相关应用

扩大button点击范围

解决:给button加分类然后重写pointInside
实现步骤:

  • 自定义按钮:创建一个自定义按钮子类,继承自 UIButton。
  • 重写 point(inside:with:):在自定义按钮类中重写此方法。该方法接受一个点,并判断该点是否在视图的范围内。你可以扩展点击区域,以便更宽泛的区域内点击时视图仍然会接收点击事件。
  • 设定点击区域扩展的大小:可以设定需要扩大点击范围的值,在四个方向上(上、下、左、右)同时增大或仅针对特定方向。
// CustomButton.h
#import <UIKit/UIKit.h>@interface CustomButton : UIButton@property (nonatomic) UIEdgeInsets hitTestEdgeInsets;@end// CustomButton.m
#import "CustomButton.h"@implementation CustomButton- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {// 计算新的扩大后的点击区域CGRect largerFrame = CGRectMake(self.bounds.origin.x - self.hitTestEdgeInsets.left,self.bounds.origin.y - self.hitTestEdgeInsets.top,self.bounds.size.width + self.hitTestEdgeInsets.left + self.hitTestEdgeInsets.right,self.bounds.size.height + self.hitTestEdgeInsets.top + self.hitTestEdgeInsets.bottom);// 判断点是否在新的点击区域内return CGRectContainsPoint(largerFrame, point);
}@end

在你的视图控制器中,将自定义按钮的 hitTestEdgeInsets 属性设置为所需的值,以扩大点击区域:

// Example usage in a view controller
CustomButton *button = [[CustomButton alloc] initWithFrame:CGRectMake(100, 100, 100, 40)];
button.backgroundColor = [UIColor systemBlueColor];
[button setTitle:@"Click Me" forState:UIControlStateNormal];// 将点击区域向四个方向各扩展10个点
button.hitTestEdgeInsets = UIEdgeInsetsMake(-10, -10, -10, -10);[self.view addSubview:button];

穿透事件

在这里插入图片描述
例如我们想点击蓝色区域时响应事件的是红色区域,但是第一响应者是蓝色区域,那么就需要我们重写(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event方法,让其无法成为响应者,这样就会让红色成为响应者

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {self.userInteractionEnabled = NO;return [super hitTest:point withEvent:event];}

总结

  • 当触摸事件发生后,系统会自动生成一个UIEvent对象,记录事件产生的时间和类型
  • 然后系统会将UIEvent事件加入到一个由UIApplication管理的事件队列中
  • 然后UIApplication将事件分发给UIWindow,主窗口会在视图层次结构中找到一个最合适的视图来处理触摸事件
  • 不断递归调用hitTest方法来找到第一响应者
  • 如果第一响应者无法响应事件,那么按照响应者链往上传递,也就是传递给自己的父视图
  • 一直传递直到UIApplication,如果都无法响应则事件被丢弃
    参考博客事件传递与响应 详解(精通iOS系列)

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

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

相关文章

苍穹外卖Day06笔记

疯玩了一个月&#xff0c;效率好低&#xff0c;今天开始捡起来苍穹外卖~ 1. 为什么不需要单独引入HttpClient的dependency&#xff1f; 因为我们在sky-common的pom.xml中已经引入了aliyun-sdk-oss的依赖&#xff0c;而这个依赖低层就引入了httpclinet的依赖&#xff0c;根据依…

Docker部署Metabase

文章目录 Docker安装MetabaseCentOS7安装Docker获取最新的 Docker 镜像启动Metabase容器在Metabase初始化时查看日志访问Metabase Metabase 的 ClickHouse 驱动程序安装环境简介删除容器创建容器下载click house驱动放入驱动重启容器将元数据库连接到 ClickHouse报错解决 Docke…

YOLOv9改进策略 | 添加注意力篇 | 一文带你改进GAM、CBAM、CA、ECA等通道注意力机制和多头注意力机制

一、本文介绍 这篇文章给大家带来的改进机制是一个汇总篇&#xff0c;包含一些简单的注意力机制&#xff0c;本来一直不想发这些内容的&#xff08;网上教程太多了&#xff0c;发出来增加文章数量也没什么意义&#xff09;&#xff0c;但是群内的读者很多都问我这些机制所以单…

PDPS15---安装过程---常遇问题---分享

目录 问题1 安装失败 1.1 运行第一步出错 1.2 解决 问题2 路径错误 2.1 错误 2.2 解决 问题3 运行失败 3.1 无法找到路径 3.2 原因分析 3.3 解决 问题4 拒绝访问 4.1 出现提示 4.2 分析 4.3 解决 问题5 许可证过期 5.1 PD找不到许可证 5.2 解决 问题1 安装失败…

Joplin:自由、安全、多功能的笔记应用

什么是 Joplin&#xff1f; Joplin是一款免费、开源的笔记和待办事项应用程序&#xff0c;可以处理整理到笔记本中的大量笔记。这些笔记是可搜索的&#xff0c;可以直接从应用程序或从您自己的文本编辑器中复制、标记和修改。笔记采用Markdown 格式 功能亮点 功能丰富&#x…

从“制造”到“智造”:“灯塔”经验助力中国制造业转型升级-转载

作者&#xff1a;Karel Eloot&#xff0c;侯文皓&#xff0c;Francisco Betti&#xff0c;Enno de Boer和Yves Giraud 作为中国实体经济的主体&#xff0c;制造业是推动中国经济发展乃至全球制造业持续增长的重要引擎。站在历史与未来交汇的新起点上&#xff0c;中国制造业将背…

3D模型如何实现拖拽打开?---模大狮模型网

在当今数字化时代&#xff0c;3D技术的应用已经深入到各行各业&#xff0c;为用户带来了更加丰富、生动的体验。然而&#xff0c;对于一些用户来说&#xff0c;打开和查看3D模型可能会面临一些困难&#xff0c;特别是在无法拖拽打开时。本文将为您揭示解决这一问题的方法&#…

【C】语⾔内存函数--超详解

1. memcpy 使⽤和模拟实现 void * memcpy ( void * destination, const void * source, size_t num ); 函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存位置。 这个函数在遇到 \0 的时候并不会停下来。 如果source和destination有任何的重叠&am…

数据结构与算法之树和二叉树的一些概念和性质

目录 前言 一、树的定义 二、树的若干术语 1.结点的度 2.叶子 3.双亲与孩子 4.兄弟 5.祖先 6.树的度 7.结点的层次 8.树的深度 9.有序树和无序树 10.森林 三、树的逻辑结构 四、树的存储结构 1.顺序存储 2.链式存储 五、二叉树 1.定义 2.二叉树的五种状态 …

SPA模式下的多页面跳转原理及实现

jQuery Mobile在SPA模式下的多页面跳转原理及实现案例 文章目录 jQuery Mobile在SPA模式下的多页面跳转原理及实现案例前言一、SPA的实现原理和代码分析1.实现原理说明&#xff08;1&#xff09;index.html&#xff08;2&#xff09;index.js&#xff08;3&#xff09;page2.ht…

前端css中线性渐变(linear-gradient)的使用

前端css中线性渐变 一、前言二、关键词句三、主要内容说明&#xff08;一&#xff09;、线性渐变方向1.角度调整方向2.负值角度&#xff0c;源码13.源码1运行效果4.关键字调整方向5.to right向右线性渐变&#xff0c;源码26.源码2运行效果 &#xff08;二&#xff09;、线性渐变…

初识C语言——第十六天

C语言中的语句结构类型:顺序/选择/循环 分支语句 if else switch 循环语句 while for do whlie goto语句 代码练习:找两个整数的最大公约数和最小公倍数 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h>//int main() //{ // int age 60; // if (ag…

YOLOv5-7.0改进(三)添加损失函数EIoU、AlphaIoU、SIoU、WIoU、MPDIoU、NWD

前言 损失函数的改进一直是涨点的重要技巧&#xff0c;本篇博客将使用六个不同损失函数对算法进行改进&#xff0c;并绘制出改进结果对比图~ 往期回顾 YOLOv5-7.0改进&#xff08;一&#xff09;MobileNetv3替换主干网络 YOLOv5-7.0改进&#xff08;二&#xff09;BiFPN替换…

基士得耶CP 6303c速印机不制版故障检修

故障&#xff1a;基士得耶CP 6303c经常提示版纸卡纸&#xff0c;重设版纸 版纸还没下滚筒&#xff0c;卡在版纸仓里面,手动滚动裁纸刀可以解决&#xff0c;但第二天又是这个毛病&#xff1b; 版纸定位传感器的灵敏度调节一下,然后给机器全面做个清洁大保养&#xff0c;尤其是传…

网工内推 | 技术支持工程师,最高15k,加班有补贴

01 星网信通 招聘岗位&#xff1a;售前技术支持 职责描述&#xff1a; 1、售前技术支持&#xff1a;技术交流、产品选型报价、方案制作等工作&#xff1b; 2、招投标支持&#xff1a;项目招标参数撰写、标书质疑、应标文件技术部分撰写及资质文件归纳准备、现场讲标及技术澄清…

vue路由知识补充(updating···)

1路由守卫中的next() next()方法表示放行&#xff0c;如果不执行此方法路由不会跳转&#xff0c;此方法可以接收一个参数 字符串路径&#xff1a;如果传递一个字符串路径&#xff0c;那么路由会重定向到该路径。 next(/home); 路由对象&#xff1a;如果传递一个路由对象&…

leetcode尊享面试——二叉树(python)

250.统计同值子树 使用dfs深度搜索&#xff0c;同值子树&#xff0c;要满足三个条件&#xff1a; 对于当前节点node&#xff0c;他的左子树血脉纯净&#xff08;为同值子树&#xff09;&#xff0c;右子树血脉纯净&#xff08;为同值子树&#xff09;&#xff0c;node的值等于…

Windows系统下修改文件夹和U盘图标实战

文章目录 知识学习一、修改磁盘图标第一步、新建.INF文件第二步、放置图标第三步、重新插入U盘第四步、隐藏与显示文件知识拓展 二、修改文件夹图标设置图标样式恢复图标样式 在日常办公中使用的是windows系统&#xff0c;系统默认的文件图标都一样&#xff0c;不利于分类整理&…

电商核心技术揭秘52:数字化内容营销创新

相关系列文章 电商技术揭秘相关系列文章合集&#xff08;1&#xff09; 电商技术揭秘相关系列文章合集&#xff08;2&#xff09; 电商技术揭秘相关系列文章合集&#xff08;3&#xff09; 电商技术揭秘四十一&#xff1a;电商平台的营销系统浅析 电商技术揭秘四十二&#…

【C++】继承 — 继承的引入、赋值切片详细讲解

前言 我们知道C语言是一门面向对象编程的语言&#xff0c;而面向对象编程有三大特性&#xff0c;它们分别是&#xff1a; 封装继承多态 目录 1. 继承的概念及定义1.1继承的概念1.2继承的定义格式1.3 继承的使用 2 基类和派生类对象赋值转换3 继承中的作用域3.1 派生类对象的存…