C++修炼:继承
Hello大家好!很高兴我们又见面啦!给生活添点passion,开始今天的编程之路!
我的博客:<但凡.
我的专栏:《编程之路》、《数据结构与算法之美》、《题海拾贝》、《C++修炼之路》
欢迎点赞,关注!
目录
1、继承引入
2、访问方式
3、继承类模板
4、基类和派生类间的转换
5、继承中的作用域
6、派生类的默认成员函数
7、继承与友元
8、继承与静态成员
9、菱形继承
10、继承和组合
C++三大特性:封装、继承、多态。封装我们了解过了,这一期我们就来介绍一下继承。
1、继承引入
继承的核心思想是允许一个类(派生类)基于另一个类(基类)扩展功能,实现代码复用和层次化设计。继承是类设计层次的复用。
我举个例子帮助大家了解一下这个东西的意义。比方说我定义一个person类,这个类的成员变量包括这个人的姓名,身高,体重,性别...,我们再定义一些类,其中每个类代表一个特殊的人。那么每个人类包含的成员变量有姓名,职业,身高,体重,性别......那么我们发现姓名身高体重性别这些是所有人共有的。但是职业不是,职业可以有可以没有,一个人可以无业,可以是学生。那么我们在设计这个人的类的时候是不是会出现很多重复的操作?
通过继承我们可以这样做:我们设计一个person类,这个类作为父类,或者叫基类(以下都成基类)。然后每个人类都继承一下这个person类,就可以把基类的私有变量继承下来。对于每个继承基类的类叫做派生类,或者子类(以下都称为派生类)。
现在我们实现以上操作:
class person //基类
{
private:string name;int height;int weight;string sex;
};
// 基类 继承方式 派生类
class person1: public person//继承
{
private:string occupation;
};
class person2 : public person
{
private:string occupation;string religion;//这个人有宗教信仰
};
2、访问方式
继承有很多种访问方式,我们继承方式有三种:public,private,protected,对于基类的对象也有这三种,组合起来有九种访问方式。
对于基类的private成员,派生类以什么方式继承都不可见。但需要注意这些private成员实际上继承下来了,只不过是不可见。
对于这九种继承方式我们简单记一下,访问方式就是取最小,就是从成员在基类的访问限定符和继承方式之间取权限较小的,其中权限public>protected>private。
举两个例子,如果我们public继承,对于基类的public成员,继承下来他的访问限定符就是public,对于protected成员,继承下来访问限定符就是protected。这也是protected和private的区别。protected的基类成员继承下来可以访问,private的基类成员继承下来无法访问。可以说protected就是因继承而产生的。
private和protected继承同理,也是取权限较小。
class person //基类
{
public:string name;int height;int weight;string sex;
};
// 基类 继承方式 派生类
class person1: public person//继承
{
public:string occupation;
};
class person2 : public person
{
public:string occupation;string religion;//这个人有宗教信仰
};
int main()
{person1 h;h.name = "小张";//如果person类成员为private成员,编译报错该对象不可访问h.height = 180;h.weight = 130;h.sex = "male";return 0;
}
一般我们都是用public继承。
3、继承类模板
以下代码就实现了一个继承类模板:
template<class T>
class stack :public vector<T>
{
public:void push(const T& x){vector<T>::push_back(x);}void pop(){vector<T>::pop_back();}const T& top(){return vector<T>::back();}bool empty(){return vector<T>::empty();}};
int main()
{stack<int> st;st.push_back(10);st.pop();return 0;
}
我们可以这样模拟实现一个stack。我们在实例化st的时候,其实也实例化出了一份vector<int>,所以我们才能使用vector里面的各种函数。
4、基类和派生类间的转换
public继承的派生类对象(注意必须是public继承)可以复制给基类的指针/基类的引用。这种现象叫切片或者切割。
class Person
{
protected:string _name; // 姓名 string _sex; // 性别 int _age; // 年龄
};
class Student : public Person
{
public:int _No; // 学号
};int main()
{Student s;Person& p1 = s;Person* p2 = &s;return 0;
}
切割下来的一部分是派生类中基类的那部分。
p1._age = 11;//访问的是切割出来的一部分
注意,基类对象不能直接复制给派生类对象。并且如果将派生类对象直接复制给基类对象不会发生切片现象。这样的话是会调用基类的拷贝构造,但其实还是会涉及到切片。
#include<iostream>
#include<string>
using namespace std;class Person
{
public:Person(){cout << 1 <<" ";}Person(Person& p){cout << 3 << " ";_age = p._age;}
protected:int _age; // 年龄
};
class Student : public Person
{
public:Student(){cout << 2 << " ";}int _No; // 学号
};int main()
{Student s;Person p = s;//调用拷贝构造return 0;
}
首先我们p还是在定义节点直接被s赋值,所以说走的是Person的拷贝构造。咱们拷贝构造必须是传引用(传值会导致无限拷贝),而我们传过去的是派生类对象,所以说会触发切片,p相当于是复制了s中的基类那一部分的值。
5、继承中的作用域
首先明确一点,虽然说派生类继承了父类,但归根结底他们算两个类,所以说有两个不同的作用域。
如果派生类和基类中有同名成员,派生类将屏蔽基类的同名成员。这种情况叫隐藏。同名函数也可以隐藏。当我们访问这个函数或者成员时,会优先在自己的作用域里找,也就是派生类作用域找,如果没有才回去查找继承下来的基类那一部分。
class Person
{
public:void Print(){cout << 10 << endl;}string _name; // 姓名 string _sex; // 性别 int _age; // 年龄
};
class Student : public Person
{
public:void Print(){cout << 5 << endl;}int _No; // 学号
};int main()
{Student s;Person& p1 = s;Person* p2 = &s;s.Print();//5p1.Print();//10p2->Print();//10return 0;
}
下面我们来看到小题熟悉一下:
以下代码的编译运行结果是什么:
class A
{
public:void fun(){cout << "func()" << endl;}
};
class B : public A
{
public:void fun(int i){cout << "func(int i)" <<i<<endl;}
};
int main()
{B b;b.fun(10);b.fun();return 0;
};
我就直接说结果了,运行以上代码会编译报错,因为两个函数构成隐藏,我们掉不到基类的fun,所以说第二次调用传入参数太少报错。
6、派生类的默认成员函数
首先派生类的构造函数必须调用基类的构造函数来初始化继承下来的那一部分成员。如果基类没有默认构造,那必须在派生类的初始化列表中显示调用。对于派生类的内置类型,初始化为随机值,自定义类型调用其构造函数(和之前一样)。基类没有默认构造会报错!
在实例化派生类的时候一定是先调用基类的默认构造。就算显示写的时候把基类的构造函数写在初始化列表的最下边也是会先去调用基类的默认构造。我们可以这样理解。其实初始化列表走的顺序本来就和初始化列表的先后没关系,和那几个成员声明的先后有关系。我们的基类成员始终是在最上面的。
对于析构,正确的析构应该是先析构派生类再析构基类。对于析构来说,由于多态的原因,编译器会把基类和派生类的析构函数的名字底层都处理为destructor。所以说两个析构函数实际上是构成隐藏关系的。那怎么办?难道需要我们手动调用父类的析构吗?其实不用。编译器为了保证先析构派生类后析构基类,会在派生类析构函数后面自己去偷偷调用基类的析构函数。编译器铺好了路,我们就不用管它啦。
但其实析构这个地方还是有坑的,什么坑我先卖个关子,下一期多态我会再说。
派生类的operator=必须调用基类的operator=完成基类的复制。需要注意的是派生类的operator=隐藏了基类的operator=,所以得显示调用基类的operator=(调用的时候指定类域)。
7、继承与友元
友元关系不能继承。比方说A和B是朋友,C继承了A,但是不能说B和A是朋友。
我们来看下面这串代码:
class Student;class Person
{
public:friend void Display(const Person& p, const Student& s);
protected:string _name; // 姓名
};// 友元关系不能继承
class Student : public Person
{
protected:int _stuNum; // 学号
};void Display(const Person& p, const Student& s)
{cout << p._name << endl;//cout << s._stuNum << endl;无法访问
}
首先友元关系不能继承,所以说display函数不能访问s的私有变量。其次这串代码由于我们在声明友元的时候Student这个类还没有定义,所以说我们在最上面声明一下。这里只能这样解决,因为如果student放在person上面student又继承不到person了。
声明的时候不需要加继承。
8、继承与静态成员
如果基类定义了static静态成员,那么整个继承体系里面只有一个这样的成员,不论派生出多少类也只有这一个static成员。
#include<iostream>
#include<vector>
using namespace std;
class A
{
public:int _b;static int _a;
};
int A::_a=0;//静态成员要在类内声明,类外定义!
class B :public A
{
public:int _c;
};
class C :public A
{
public:int _d;
};
int main()
{A aa;B bb;C cc;bb._a = 10;cout << cc._a << endl;//10return 0;
};
9、菱形继承
C++支持多继承,就是一个派生类继承两个基类
class A
{
public:int _b;static int _a;
};
int A::_a=0;//静态成员要在类内声明,类外定义!
class B
{
public:int _c;
};
class C :public A ,public B//多继承
{
public:int _d;
};
但是这也带来了一个问题,就是菱形继承。
如果A继承了B和C,B和C又都继承了D,此时就构成了菱形继承。菱形继承会带来一些问题,第一就是数据冗余。因为A中有两份D的变量。第二就是二义性。A访问继承的D的变量需要指定访问的路径。
#include<iostream>
#include<vector>
using namespace std;
class D
{
public:int _d;
};class C :public D
{
public:int _c;
};
class B:public D
{
public:int _b;
};
class A:public B,public C
{
public:int _a;
};
int main()
{A a;a._d = 0;return 0;
};
如果直接访问会报错:
需要按照以下方式访问:
A a;a.B::_d = 0;a.C::_d = 1;
那么解决办法是什么呢?第一就是虚继承。在继承A的时候加上virtual关键字 ,这样D中的成员变量只会实例化出一份。并且不需要访问方式限定,直接正常访问就行了。
class D
{
public:int _d;
};class C : virtual public D
{
public:int _c;
};
class B: virtual public D
{
public:int _b;
};
class A:public B,public C
{
public:int _a;
};
int main()
{A a;a._d = 0;//正常访问return 0;
};
但是这种方式会造成额外的开销,所以说第二个解决办法就是不要写出菱形继承。当然也有的情况是不得不写菱形继承。那么这种情况再考虑用virtual关键字。
接下来我们看一道小题:
多继承中指针偏移问题?下面说法正确的是()
A: p1==p2==p3 B:p1<p2<p3 C:p1==p3!=p2 D:p1!=p2!=p3
#include<iostream> using namespace std; class Base1 { public: int _b1; }; class Base2 { public: int _b2; }; class Derive : public Base1, public Base2 { public: int _d; }; int main() {Derive d;Base1* p1 = &d;Base2* p2 = &d;Derive* p3 = &d;return 0; }
我先公布答案,这道题选C。我把这道题的图画出来大家就理解了。
在类中,先继承的在上面,后继承的在下面,最后是自己的成员变量。所以说这道题选C。
图中这个类包含的三部分每部分之间都有一些空隙,其实这个空隙可能有,可能没有,受内存对齐规则的影响。
10、继承和组合
public继承是一种is-a的关系,每一个派生类对象都是一个基类对象。而组合是一种has-a的关系,假设B组合A,每个B对象都有一个A对象。
class A
{
public:int _a;
};
//is-a
class B :public A
{
public: int _b;
};//has-a
class C
{
public:int _c;class A;
};
继承这种复用方式叫白箱复用。另外友元也是一种白箱复用。白和黑是相对于可见性来说的。与白箱复用相对的黑箱复用,不如组合和接口,都是黑箱复用。
白箱复用耦合度高,比方说基类和派生类,更改基类会影响到派生类。而组合耦合度低,因为我们不关心被组合的类是如何实现的,我们只需调一下他的接口就行(比如之前模拟实现stack和queue)。
写代码的时候我们要优先使用组合,因为使用继承其实是会破坏封装的。但是必要时也得用继承,包括下一篇我们要说的多态也是在继承的基础上实现的。
好了,今天的内容就分享到这,我们下期再见!
相关文章:
C++修炼:继承
Hello大家好!很高兴我们又见面啦!给生活添点passion,开始今天的编程之路! 我的博客:<但凡. 我的专栏:《编程之路》、《数据结构与算法之美》、《题海拾贝》、《C修炼之路》 欢迎点赞,关注&am…...
Mysql新增
插入一个记录需要的时间由下列因素组成,其中的数字表示大约比例: 连接:(3)发送查询给服务器:(2)分析查询:(2)插入记录:(1x记录大小)插入索引:(1x索引&#x…...
华秋2025电子设计与制造技术研讨会(华东站)成功举办!
“探索科技前沿,共筑创新未来”——华秋“2025电子设计与制造技术研讨会第一站:华东站”在江苏苏州圆满落幕。 随着电子信息产业的持续增长和数字化经济的加速转型,数字化电子供应链的作用愈发显著。本届研讨聚焦EDA设计、DFM软件分析、多层…...
[学习] RTKLib详解:qzslex.c、rcvraw.c与solution.c
RTKLib详解:qzslex.c、rcvraw.c与solution.c 本文是 RTKLlib详解 系列文章的一篇,目前该系列文章还在持续总结写作中,以发表的如下,有兴趣的可以翻阅。 [学习] RTKlib详解:功能、工具与源码结构解析 [学习]RTKLib详解…...
【Ubuntu】neovim Lazyvim安装与卸载
安装neovim # 下载 AppImage wget https://github.com/neovim/neovim/releases/latest/download/nvim-linux-x86_64.appimage# 添加执行权限 chmod ux nvim-linux-x86_64.appimage# 移动到系统路径,重命名为 nvim sudo mv nvim-linux-x86_64.appimage /usr/local/b…...
数据结构(一) 绪论
一. 时间复杂度: (1)定义: 时间复杂度是衡量算法执行时间随输入规模(通常用n表示)增长的变化趋势的指标,时间复杂度用O符号表示 用于描述算法在最坏情况下或平均情况下的时间需求 时间复杂度关注的是操作次数的增长率,而非具体执行时间 常见的时间复杂度由小到大依次…...
数据库事务并发问题
目录 脏读 幻读 不可重复读 三者的区别 脏读、幻读和不可重复读是在数据库并发操作中可能出现的问题,以下是对它们的详细介绍: 脏读 定义:指一个事务读取了另一个未提交事务修改的数据。示例:事务 A 修改了一条数据…...
Android之横向滑动列表
文章目录 前言一、效果图二、使用步骤1.xml布局2.代码3.HomeHxBean3.adapter4.item布局5.两个drawable 总结 前言 横向滑动列表有多种实现方式,也可以用tablayout,也可以用recyclerview,今天主要介绍recyclerview。 一、效果图 二、使用步骤…...
系统稳定性之上线三板斧
📕我是廖志伟,一名Java开发工程师、《Java项目实战——深入理解大型互联网企业通用技术》(基础篇)、(进阶篇)、(架构篇)清华大学出版社签约作家、Java领域优质创作者、CSDN博客专家、…...
aardio - godking.vlistEx.listbar + win.ui.tabs 实现多标签多页面切换
方法一: import win.ui; import godking.vlistEx.listbar; import fonts.fontAwesome; /*DSG{{*/ mainForm win.form(text"vlistEx - table adapter";right895;bottom503) mainForm.add({ custom{cls"custom";text"自定义控件";lef…...
鸿蒙 核心与非核心装饰器
HarmonyOS NEXT 版本中完整的 ArkTS 装饰器分类整理(含核心与非核心装饰器,已剔除废弃特性) 一、核心装饰器(Essential Decorators) 1. 组件基础 装饰器功能Entry应用入口组件,每个模块必须且仅有一个&am…...
TypeScript 知识框架
一、TypeScript 基础 1. 类型系统 基本类型: number, string, boolean, null, undefined, symbol, bigint 引用类型: object, array, function, class 特殊类型: any, unknown, void, never 类型推断与类型注解 类型断言 (as 语法和 <Type> 语法) 2. 接口与类型别名 接口…...
web-ui开源程序是建立在浏览器使用的基础上,旨在使 AI 代理可以访问网站
一、软件介绍 文末提供程序和源码下载 web-ui开源程序是建立在浏览器使用的基础上,旨在使 AI 代理可以访问网站。WebUI:基于 Gradio 构建,支持大部分 browser-use 功能。此 UI 设计为用户友好型,并支持与浏览器代理轻松交互。扩…...
【ns3】TCP三次握手源码解析
文章目录 TCP三次握手过程三次握手源码 TCP三次握手过程 三次握手源码 下面是ns3里三次握手整体过程的源码,和上面图解一一对应: TCP socket的状态枚举: 整体过程: 客户端首先connect:tcp-socket-base::connect调用Do…...
【YOLO模型】参数全面解读
使用YOLO模型时,需要调节各种参数,网络文章和官方文档有点不方便,整理了下面的内容备用: 获取最全最新的参数列表: Ultralytics官方文档: 这是获取YOLOv11(以及YOLOv8等)最权威、最详细参数信息的地方。通…...
跨境电商定价革命:亚马逊“逆向提价“策略背后的价值重构逻辑
导言:打破价格魔咒的销量奇迹 2024年Q3亚马逊平台上演商业悖论:在TOP5000卖家中,12%实施5%-15%温和提价的商户,41%实现单量30.4%的季度增长。这一现象颠覆"低价即流量"的电商铁律,揭开新消费时代"价值定…...
Kafka、RabbitMQ、RocketMQ的区别
以下是 RabbitMQ、RocketMQ、Kafka 的核心区别对比: 一、架构设计差异 Kafka 基于分布式日志的发布-订阅模型,通过分区(Partition)实现水平扩展,依赖 ZooKeeper 管理集群消费者通过消费者组(Consumer G…...
win10 局域网内聊天
在 Windows 10 的局域网 中,如果你想实现 多个用户之间的聊天功能,可以选择以下几种方案,取决于你需要的是: • ✅ 命令行纯文字聊天(如 Linux talk) • ✅ 图形界面聊天室 • ✅ 局域网广播消息 • ✅ 多人…...
【前端三剑客】Ajax技术实现前端开发
目录 一、原生AJAX 1.1AJAX 简介 1.2XML 简介 1.3AJAX 的特点 1.3.1AJAX 的优点 1.3.2AJAX 的缺点 1.4AJAX 的使用 1.4.1核心对象 1.4.2使用步骤 1.4.3解决IE 缓存问题 1.4.4AJAX 请求状态 二、jQuery 中的AJAX 2.1 get 请求 2.2 post 请求 三、跨域 3.1同源策略…...
论文学习_Trex: Learning Execution Semantics from Micro-Traces for Binary Similarity
摘要:检测语义相似的函数在漏洞发现、恶意软件分析及取证等安全领域至关重要,但该任务面临实现差异大、跨架构、多编译优化及混淆等挑战。现有方法多依赖语法特征,难以捕捉函数的执行语义。对此,TREX 提出了一种基于迁移学习的框架…...
数据压缩的概念和优缺点
一、数据压缩的概念 数据压缩是通过特定算法(压缩算法)对数据进行重新编码,以减少数据存储空间或传输带宽的技术。其核心目标是在不丢失关键信息(或允许一定程度信息损失)的前提下,降低数据量,…...
spaCy基础入门
spaCy 概览说明 spaCy 是一个现代、快速、工业级 NLP 工具库,专门为实际工程应用设计,提供: • 分词(Tokenization) • 词性标注(POS Tagging) • 命名实体识别(NER) •…...
vue3项目创建-配置-elementPlus导入-路由自动导入
目录 方法一:create-vue 方法二 :Vite Vue Vite.config.ts配置 引入element-plus 安装 如何在项目中使用 Element Plus 完整引入 按需导入 vue3vite中自动配置路由的神器:vite-plugin-pages 1. 安装 2、修改vite.config.js中配置…...
2025年的电脑能装win7吗_2025年组装电脑装win7详细图文教程
2025年的电脑能装win7吗?2025年的电脑可以安装Win7,但存在一些限制和挑战。2025年的电脑基本上是14代和15代处理器,需要特定的条件和步骤才能安装win7,并且只能采用独立显卡,因为没有集成显卡驱动。另外注意目前2025年…...
windowsC++操作ADB
文章目录 一、ADB基础1. 工作原理2. 安装与配置 二、常用ADB指令分类1. 设备连接与管理2. 文件传输3. 应用管理4. 设备交互5. 系统信息6. 日志与调试7. 网络与端口转发 三、高级用法1. 多设备管理2. 无线ADB连接3. 批量执行命令4. ADB脚本示例 四、常见问题与解决方案五、注意事…...
Springboot实现重试机制
背景 研发工作中时常遇到要和其他服务对接,依赖对方能力的情况,最恶心的是对方提供的服务不稳定,时灵时不灵的,进而影响到自己功能的稳定性。万一发生了这种事,做为研发,咱该怎么办?通过容错直接…...
CS内网渗透 ----【内网渗透实战】PsExec vs Telnet:建立IPC通道实现横向移动与域控上线全解析
目录 1. 什么是 PsExec? 2. 什么是 Telnet? 3. PsExec 与 Telnet 的区别及优势 3.1 主要区别 3.2 内网渗透中的优势 4. 实际案例 —— 使用 PsExec 上线域控主机 案例背景 操作步骤 案例效果 5. 总结 利用 PsExec 建立 IPC 通道 —— IPC 的定…...
第二十三天打卡
作业: 整理下全部逻辑的先后顺序,看看能不能制作出适合所有机器学习的通用pipeline 数据预处理 → 特征选择 → 降维 → 模型训练 import pandas as pd import numpy as np from sklearn.model_selection import train_test_split, GridSearchCV from sk…...
aardio - 将文本生成CSS格式显示
import win.ui; /*DSG{{*/ var winform win.form(text"aardio form";right759;bottom469) winform.add( button{cls"button";text"Button";left340;top130;right430;bottom180;z3}; edit{cls"edit";text"我是一串文本";lef…...
【漫话机器学习系列】256.用 k-NN 填补缺失值
用 k-NN 填补缺失值:原理、实现与应用 在实际的数据科学项目中,我们经常会遇到数据缺失(Missing Values)的问题。缺失值如果处理不当,不仅会影响模型训练,还可能导致最终结果偏差。 今天,我们…...
tomcat与nginx之间实现多级代理
准备工作 准备5台虚拟主机;至少准备3台虚拟主机; 设备1作为代理服务器;设备2与设备4作为处理静态资源请求服务器(使用nginx);设备3与设备5作为处理动态资源服务器(使用tomcat) 设…...
商业航天运动控制系统中的高可靠性芯片解决方案:挑战、策略与应用研究
摘要:随着商业航天领域的迅速发展,运动控制系统对芯片的可靠性提出了前所未有的挑战。本文深入探讨了商业航天运动控制系统中芯片可靠性面临的挑战,包括宇宙辐射效应、极端环境适应性及系统级可靠性保障等。同时,通过案例研究展示…...
[Java实战]Spring Boot 3 整合 Ehcache 3(十九)
[Java实战]Spring Boot 3 整合 Ehcache 3(十九) 引言 在微服务和高并发场景下,缓存是提升系统性能的关键技术之一。Ehcache 作为 Java 生态中成熟的内存缓存框架,其 3.x 版本在性能、功能和易用性上均有显著提升。本文将详细介绍…...
【Flask全栈开发指南】从零构建企业级Web应用
目录 🌟 前言🏗️ 技术背景与价值🚧 当前技术痛点🛠️ 解决方案概述👥 目标读者说明 🔍 一、技术原理剖析📊 核心概念图解💡 核心作用讲解🧩 关键技术模块说明⚖️ 技术选…...
使用docker安装clickhouse集群
1、简介 clickhouse 作为大数据场景中,实现快速检索的常用列式存储数据库,采用物理机部署,会在数据量大的场景中,物理机器存储达到阈值需要扩容,会带来比较大的问题,因此,使用docker部署clickho…...
佰力博科技准静态d33测试的注意事项
准静态d33测试是测量压电材料纵向压电应变常数的重要方法,其注意事项包括以下几个方面: 选择合适的测量设备 准静态d33测试需要使用专用的压电测试仪,如佰力博PEAI1000高精度压电分析仪、准静态d33测量仪或PCA1000压电陶瓷综合参数分析仪。这…...
iOS设备投屏Archlinux
我的iphone手机屏太小,我想把手机投到archlinux电脑上看。与是我就想找一个免费的软件。 UxPlay https://github.com/FDH2/UxPlay GPLv3,开源。原来只支持 AirPlay Mirror 协议,现在新增 支持来自 AirPlay 的纯音频 (Apple Los…...
VUE_UI组件的二次封装
属性和事件 <template><div><myInput a"1" b"2" c"3" change"() > {}"></myInput></div> </template>myInput.vue <template><div><el-input v-bind"$attrs">&…...
算法·KMP
KMP算法的思想 想要一次性遍历模板串 s 1 s_1 s1,不在匹配失败时重新开始遍历子串 s 2 s_2 s2,实现模板串不回退的效果。 KMP数组的理解 KMP数组有两种定义:一是匹配失败后,子串 s 2 s_2 s2应该回退的位置,一种…...
如何正确地写出单例模式
如何正确地写出单例模式 | Jarks Blog 枚举方式: public class SingletonObject {private SingletonObject() {}/*** 枚举类型是线程安全的,并且只会装载一次*/private enum Singleton {INSTANCE;private final SingletonObject instance;Singleton() {…...
Mac M系列 安装 jadx-gui
安装 Homebrew在终端中执行以下命令(需管理员密码): 安装 Homebrew(官方源) /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"国内用户可用镜像源加速&…...
水滴Android面经及参考答案
目录 static 关键字有什么作用,它修饰的方法可以使用非静态的成员变量吗? Java 中创建线程有几种方式? wait 和 sleep 的区别,如何打断 sleep? Java 垃圾回收的目的是什么,垃圾回收机制是怎样的? Java 的垃圾回收(GC)机制是如何工作的? 请解释 Java 内存模型(J…...
《猜拳游戏》
综合案例《猜拳游戏》 需求: 本游戏是一款单机游戏,人机交互 规则: 需要双方出拳:石头、剪刀、布 赢: 石头 → 剪刀剪刀 → 布布 → 石头 平: 两边出拳相等 输: … 实现: 选择对…...
Mysql索引优化
一、索引 1. 主键索引(Primary Index) 定义 主键索引是一种特殊的唯一索引,用于唯一标识表中的每一行数据。每个表最多有一个主键索引,且索引列不允许为 NULL,自动添加 UNIQUE 和 NOT NULL 约束。 特点:…...
Postgresql与openguass对比
背景介绍 PostgreSQL是世界上最先进的开源关系型数据库,以其强大的功能、稳定性和可扩展性著称。而openGauss是华为公司于2020年6月30日开源的数据库系统,内核基于PostgreSQL 9.2.4版本演进而来。值得注意的是,PostgreSQL 11.3版本拥有290个数…...
线程的概念和控制
自从20世纪60年代提出了进程的概念之后,操作系统一直以进程作为独立运行的基本单位。到了20世纪80年代,人们又提出了比进程更小的、能独立运行的基本单位——线程。提出线程的目的是试图提高系统并发执行的程度,从而进一步提高系统的吞吐量。…...
如何配置activemq,支持使用wss协议连接。
1、到阿里云申请一个证书,通过后下载jks证书。 2、配置activemq: 打开activemq安装目录中“conf/activemq.xml”,增加以下记录: <transportConnectors> <transportConnector name"wss" uri"…...
【言语】刷题3
front:刷题2 题干 超限效应介绍冰桶挑战要避免超限效应 B明星的作用只是病痛挑战的一个因素,把握程度才是重点,不是强化弱化明星作用,排除 A虽没有超限效应,但是唯一的点出“冰桶效应”的选项,“作秀之嫌…...
关于 ast: Babel AST 全类型总览
AST 的每个节点都有一个 type 字段,用来标识它的语法类型。 程序结构节点 type说明示例Program整个程序的根节点整体代码结构BlockStatement大括号代码块 {}if、function、for 等的主体ExpressionStatement表达式语句(如 a b;)EmptyStatem…...
STM32 内存
根据STM32的存储器映射机制,其32位地址总线可访问4GB逻辑地址空间(0x00000000-0xFFFFFFFF),但实际物理地址分配由芯片厂商定义。以下是STM32完整的地址映射结构及关键区域说明: 一、地址空间整体架构 4GB地址空间划分…...