当前位置: 首页 > news >正文

C++ 多态:原理、实现与应用

目录

 

引言

一、多态的概念

二、多态的定义及实现

(一)构成条件

(二)虚函数的深入理解

(三)虚函数的重写(覆盖)

三、抽象类

(一)概念

(二)接口继承和实现继承

四、多态的原理

(一)虚函数表

(二)动态绑定与静态绑定

五、单继承和多继承关系中的虚函数表

(一)单继承中的虚函数表

​编辑

​编辑

(二)多继承中的虚函数表

六、C++11 override 和 final

(一)final

(二)override

七、重载、覆盖(重写)、隐藏(重定义)的对比

(一)重载

(二)覆盖(重写)

(三)隐藏(重定义)

​编辑

八、结语


 

引言

在 C++ 编程世界里,多态是一个强大且迷人的特性。它允许我们以统一的接口来处理不同类型的对象,实现 “一种接口,多种形态”。这不仅提升了代码的灵活性与可维护性,还极大地增强了程序的扩展性。今天,就让我们深入探究 C++ 多态的奥秘。

一、多态的概念

多态,通俗来讲,就是同一行为在不同对象上表现出不同的状态。就像现实生活中,买票这个行为,普通人买票是全价,学生买票是半价,军人买票可能有优先特权。在 C++ 中,多态使得我们可以用相同的函数调用,根据对象类型的不同执行不同的操作。

二、多态的定义及实现

(一)构成条件

1. 虚函数:被  virtual  关键字修饰的类成员函数。例如:

cppclass Person {public:virtual void BuyTicket() {std::cout << "买票 - 全价" << std::endl;}};

 

 

1. 虚函数覆盖:派生类中定义与基类虚函数返回值类型、函数名字、参数列表完全相同的虚函数。如:

cppclass Student : public Person {public:virtual void BuyTicket() {std::cout << "买票 - 半价" << std::endl;}};

 

1. 通过基类指针或引用调用虚函数:

###不可用子类指针或引用调用虚函数(- 使用父类指针或引用可以指向不同的子类对象,通过相同的父类接口来调用不同子类实现的方法,从而体现多态性。如果仅使用子类指针或引用,只能调用子类自身定义或重写的方法,无法通过统一的父类接口来实现多种不同的行为,也就无法充分体现多态的特性。

###不可用父类对象(父类对象调用的方法是在父类中定义的方法,不会调用子类重写后的方法。多态的核心是根据对象的实际类型来决定调用哪个类中重写的方法,而父类对象的类型是固定的,不能根据不同的情况表现出不同的行为,无法体现多态性。

cppvoid Func(Person& people) {people.BuyTicket();}int main() {Person Mike;Student Johnson;Func(Mike);Func(Johnson);return 0;}

 

 

在上述代码中, Func  函数通过基类  Person  的引用调用  BuyTicket  虚函数,根据传入对象是  Person  还是  Student ,会分别执行对应的  BuyTicket  函数版本,实现多态行为。

(二)虚函数的深入理解

虚函数是实现多态的关键。当类中包含虚函数时,编译器会为该类生成一个虚函数表(虚表)不同于继承,每个对象中会包含一个指向虚函数表的指针( vptr )。在调用虚函数时,程序通过对象的  vptr  找到虚函数表,再从表中获取对应函数的地址进行调用。

 

例如:

cppclass Base {public:virtual void Func1() {std::cout << "Base::Func1" << std::endl;}virtual void Func2() {std::cout << "Base::Func2" << std::endl;}private:int _b = 1;};

 

 

对于包含虚函数的  Base  类对象,其大小除了成员变量占用的空间外,还会包含一个  vptr  的大小(通常在 32 位系统下为 4 字节,64 位系统下为 8 字节)。

(三)虚函数的重写(覆盖)

派生类重写基类虚函数时,需满足函数签名(返回值类型、函数名、参数列表)完全相同。不过存在两个例外:

 

1. 协变:基类与派生类虚函数返回值类型不同,即基类虚函数返回基类对象的指针或引用,派生类虚函数返回派生类对象的指针或引用。例如:

cppclass A {};class B : public A {};class Person {public:virtual A* f() {return new A;}};class Student : public Person {public:virtual B* f() {return new B;}};

 

 

1. 析构函数的重写:如果基类的析构函数为虚函数,派生类析构函数只要定义,无论是否加  virtual  关键字,都与基类的析构函数构成重写。尽管函数名不同(基类  ~Person ,派生类  ~Student ),但编译器会对析构函数名称做特殊处理,统一成  destructor 

cppclass Person {public:virtual ~Person() {std::cout << "~Person()" << std::endl;}};class Student : public Person {public:virtual ~Student() {std::cout << "~Student()" << std::endl;}};

三、抽象类

(一)概念

包含纯虚函数(在虚函数声明后面加上  = 0 )的类称为抽象类,也叫接口类。抽象类不能实例化对象,派生类继承抽象类后,只有重写纯虚函数才能实例化对象。纯虚函数规范了派生类必须实现的接口。

cppclass Car {public:virtual void Drive() = 0;};class Benz : public Car {public:virtual void Drive() {std::cout << "Benz - 舒适" << std::endl;}};class BMW : public Car {public:virtual void Drive() {std::cout << "BMW - 操控" << std::endl;}};void Test() {Car* pBenz = new Benz;pBenz->Drive();Car* pBMW = new BMW;pBMW->Drive();}

 

(二)接口继承和实现继承

普通函数的继承是实现继承,派生类继承基类函数的实现,可以直接使用函数。虚函数的继承是接口继承,派生类继承基类虚函数的接口,目的是为了重写以达成多态。所以如果不实现多态,就不要把函数定义成虚函数。

四、多态的原理

(一)虚函数表

当类中有虚函数时,编译器会为类创建虚函数表。以简单的单继承为例:

cppclass Base {public:virtual void Func1() {std::cout << "Base::Func1" << std::endl;}private:int _b = 1;};class Derive : public Base {public:virtual void Func1() {std::cout << "Derive::Func1" << std::endl;}private:int _d = 2;};

 

 

在上述代码中, Base  类对象包含  vptr  和成员变量  _b , Derive  类对象包含从  Base  继承的部分( vptr  和  _b )以及自身的成员变量  _d 。 Derive  重写了  Func1 ,其虚函数表中  Func1  的地址是  Derive::Func1  的地址,而从  Base  继承的虚函数(如还有其他未重写虚函数)会将基类虚函数表中的对应函数地址拷贝过来。

1.派生类对象d中也有一个虚表指针,d对象由两部分构成,一部分是父类继承下来的成员,虚表指针也就是存在部分的另一部分是自己的成员。
2. 基类b对象和派生类d对象虚表是不一样的,这里我们发现Func1完成了重写,所以d的虚表中存的是重写的Derive::Func1,所以虚函数的重写也叫作覆盖,覆盖就是指虚表中虚函数的覆盖。重写是语法的叫法,覆盖是原理层的叫法。
3. 另外Func2继承下来后是虚函数,所以放进了虚表,Func3也继承下来了,但是不是虚函数,所以不会放进虚表。
4. 虚函数表本质是一个存虚函数指针的指针数组,一般情况这个数组最后面放了一个nullptr。
5. 总结一下派生类的虚表生成:a.先将基类中的虚表内容拷贝一份到派生类虚表中 b.如果派生类重写了基类中某个虚函数,用派生类自己的虚函数覆盖虚表中基类的虚函数 c.派生类自己新增加的虚函数按其在派生类中的声明次序增加到派生类虚表的最后。
6. 这里还有一个我们很容易混淆的问题:虚函数存在哪的?虚表存在哪的? 答:虚函数存在虚表,虚表存在对象中。注意上面的回答的错的。但是很多童鞋都是这样深以为然的。注意虚表存的是虚函数指针,不是虚函数,虚函数和普通函数一样的,都是存在代码段的,只是他的指针又存到了虚表中。另外对象中存的不是虚表,存的是虚表指针。

那么虚表存在哪里

 

答案是常量区

(二)动态绑定与静态绑定

1. 静态绑定:又称前期绑定,在程序编译期间确定程序的行为,例如函数重载,编译时就能确定调用哪个函数版本。

 

2. 动态绑定:又称后期绑定,在程序运行期间,根据具体对象的类型确定调用的具体函数,多态就是通过动态绑定实现的。

五、单继承和多继承关系中的虚函数表

(一)单继承中的虚函数表

cppclass Base {public:virtual void func1() {std::cout << "Base::func1" << std::endl;}virtual void func2() {std::cout << "Base::func2" << std::endl;}private:int _b;};class Derive : public Base {public:virtual void func1() {std::cout << "Derive::func1" << std::endl;}virtual void func3() {std::cout << "Derive::func3" << std::endl;}virtual void func4() {std::cout << "Derive::func4" << std::endl;}private:int _d;};

 

 

在单继承中,派生类会拷贝基类虚函数表内容,并重写被覆盖的虚函数地址,新增的虚函数按声明顺序添加到虚函数表后面。

观察下图中的监视窗口中我们发现看不见func3和func4。

这里是编译器的监视窗口故意隐藏了这两个函数,也可以认为是他的一个小bug。那么我们如何查看d的虚表呢?下面我们使用代码打印出虚表中的函数

class Base {
public:
    virtual void func1() { std::cout << "Base::func1" << std::endl; }
    virtual void func2() { std::cout << "Base::func2" << std::endl; }
private:
    int _b;
};

class Derive : public Base {
public:
    virtual void func1() { std::cout << "Derive::func1" << std::endl; }
    virtual void func3() { std::cout << "Derive::func3" << std::endl; }
    virtual void func4() { std::cout << "Derive::func4" << std::endl; }
private:
    int _d;
};
typedef void(*VFPTR) ();
void PrintVTable(VFPTR vTable[])
{
    // 依次取虚表中的虚函数指针打印并调用。调用就可以看出存的是哪个函数
    cout << " 虚表地址>" << vTable << endl;
    for (int i = 0; vTable[i] != nullptr; ++i)
    {
        printf(" 第%d个虚函数地址 :0X%x,->", i, vTable[i]);
        VFPTR f = vTable[i];
        f();
    }
    cout << endl;
}
int main()
{
    Base b;
    Derive d;
    VFPTR * vTableb = (VFPTR*)(*(int*)&b);
    PrintVTable(vTableb);
    VFPTR* vTabled = (VFPTR*)(*(int*)&d);
    PrintVTable(vTabled);
    return 0;
}

(二)多继承中的虚函数表

cppclass Base1 {public:virtual void func1() {std::cout << "Base1::func1" << std::endl;}virtual void func2() {std::cout << "Base1::func2" << std::endl;}private:int b1;};class Base2 {public:virtual void func1() {std::cout << "Base2::func1" << std::endl;}virtual void func2() {std::cout << "Base2::func2" << std::endl;}private:int b2;};class Derive : public Base1, public Base2 {public:virtual void func1() {std::cout << "Derive::func1" << std::endl;}virtual void func3() {std::cout << "Derive::func3" << std::endl;}private:int d1;};

 

 

多继承时,派生类会有多个虚函数表(分别对应各个基类),未重写的虚函数放在第一个继承基类部分的虚函数表中,重写的虚函数会更新对应虚函数表中的函数地址。

但是我们观察到

六、C++11 override 和 final

(一)final

 final  修饰虚函数,表示该虚函数不能再被重写。例如:

cppclass Car {public:virtual void Drive() final {}};class Benz : public Car {public:// 编译报错,Drive不能被重写virtual void Drive() {std::cout << "Benz - 舒适" << std::endl;}};

 

(二)override

 override  用于检查派生类虚函数是否重写了基类某个虚函数,如果没有重写则编译报错。例如:

cppclass Car {public:virtual void Drive() {}};class Benz : public Car {public:virtual void Drive() override {std::cout << "Benz - 舒适" << std::endl;}};

 

七、重载、覆盖(重写)、隐藏(重定义)的对比

(一)重载

- 作用域:两个函数在同一作用域。

 

- 条件:函数名相同,参数不同(个数、类型、顺序)。

(二)覆盖(重写)

- 作用域:两个函数分别在基类和派生类的作用域。

 

- 条件:函数名、参数、返回值都必须相同(协变除外),且函数必须是虚函数。

(三)隐藏(重定义)

- 作用域:两个函数分别在基类和派生类的作用域。

 

- 条件:函数名相同,基类和派生类的同名函数不构成重写就是重定义。

八、结语

C++ 多态是一个复杂而精妙的特性,从概念到实现,从原理到应用,都有着丰富的内涵。掌握多态,能让我们编写出更加灵活、可维护和高效的代码。在实际编程中,合理运用多态,结合虚函数、抽象类等知识,可以更好地应对各种复杂的业务需求。希望通过这篇博客,大家能对 C++ 多态有更深入的理解和掌握。

 

相关文章:

C++ 多态:原理、实现与应用

目录 引言 一、多态的概念 二、多态的定义及实现 &#xff08;一&#xff09;构成条件 &#xff08;二&#xff09;虚函数的深入理解 &#xff08;三&#xff09;虚函数的重写&#xff08;覆盖&#xff09; 三、抽象类 &#xff08;一&#xff09;概念 &#xff08;二&…...

多模态大语言模型arxiv论文略读(五十八)

How Does the Textual Information Affect the Retrieval of Multimodal In-Context Learning? ➡️ 论文标题&#xff1a;How Does the Textual Information Affect the Retrieval of Multimodal In-Context Learning? ➡️ 论文作者&#xff1a;Yang Luo, Zangwei Zheng, …...

TS 枚举类型

枚举 参数为枚举成员中的一个 数字枚举 字符串枚举 枚举特点 、 缺点&#xff1a;转为JS代码时会编译成JS代码&#xff0c;增大开销...

Python容器与循环:数据处理的双剑合璧

Python作为一门简洁强大的编程语言&#xff0c;其容器类型和循环结构的完美结合为数据处理提供了极大的便利。本文将带领初学者深入理解Python中的四大容器&#xff08;列表、元组、字典、集合&#xff09;以及它们与循环结构的配合使用&#xff0c;助你掌握数据处理的核心技能…...

ST-LINKV2仿真器下载

ST-LINKV2仿真器 — 正点原子资料下载中心 1.0.0 文档...

RAGFlow 接入企业微信应用实现原理剖析与最佳实践

背景 近期有医美行业客户咨询我们智能客服产品&#xff0c;期望将自己企业的产品、服务以及报价信息以企微应用的方式给到客户进行体验互动&#xff0c;提升企业运营效率。关于企业微信对接&#xff0c;我们分享下最佳实践&#xff0c;抛砖引玉。效果图如下&#xff1a; 这里也…...

大模型实践:图文解锁Ollama在个人笔记本上部署llm

使用在线模型服务时&#xff0c;我们常常需要支付API调用费用&#xff0c;这对于个人开发者或小型组织来说可能是一笔不小的开支。那么&#xff0c;有没有方法可以在本地免费使用这些强大的模型呢&#xff1f;答案是肯定的——Ollama就是这样一个工具。 当然如果是比较大的组织…...

如何提高情商?(优化版)

引言 提高情商&#xff08;EQ&#xff09;是一个需要长期练习和自我反思的过程&#xff0c;核心在于理解自己、管理情绪、共情他人并有效沟通。以下是一些具体且可操作的方法&#xff0c;结合理论和实际场景&#xff0c;帮助你逐步提升&#xff1a; 一、核心方法&#xff1a;…...

学习黑客Linux权限

在 Linux 的王国里&#xff0c;“权限”就是装备与技能加成&#xff1a;决定谁能拔剑&#xff08;读 r&#xff09;、挥剑&#xff08;写 w&#xff09;、进入房间&#xff08;执行 x&#xff09;。本文用“闯关升级”视角&#xff0c;把常见 rwx、八进制数字、SUID/SGID/Stick…...

信息系统监理师第二版教材模拟题第二组(含解析)

信息系统监理师模拟题第二组(30题) 监理理论与法规 根据《信息系统工程监理暂行规定》,监理单位应当独立于( ) A. 建设单位和承建单位 B. 政府监管部门 C. 行业组织 D. 最终用户答案:A 解析:监理单位应当保持独立性,不得与建设单位和承建单位有隶属关系或其他利害关系…...

C与指针——输入输出

错误定位 当一个库函数出错时&#xff0c;errno会被重置 perror(const char* s);\\输出s: errno 对应的错误信息 \\如果单独想要错误信息可以 char* e strerror(errno);\\系统错误码转换为对应的错误信息字符串输出缓冲区 一般输出缓冲区满的时候才刷新&#xff0c;也就是…...

RR(Repeatable Read)级别如何防止幻读

在 MySQL 数据库事务隔离级别中&#xff0c;RR&#xff08;可重复读&#xff09; 通过 MVCC&#xff08;多版本并发控制&#xff09; 和 锁机制 的组合策略来避免幻读问题。 一、MVCC机制&#xff1a;快照读与版本控制 快照读&#xff08;Snapshot Read&#xff09; 每个事务启…...

Python之学习笔记(六)

文章目录 1. 字典&#xff08;Dictionary&#xff09;2. 集合&#xff08;Set&#xff09;3. 字典 vs 集合4. 应用场景5. 注意事项 Python中的字典&#xff08; dict&#xff09;和集合&#xff08; set&#xff09;是两种高效且常用的数据结构&#xff0c;适用于不同的场景。…...

Easy云盘总结篇-文件上传02

说在前面&#xff1a;此项目是跟着B站一位大佬写的&#xff0c;不分享源码&#xff0c;支持项目付费 文件预览 主要分视频和其他文件预览&#xff0c;但实现逻辑相同&#xff0c;只是请求路径有区别。 这段逻辑&#xff1a; 拿视频预览举例&#xff1a; 视频开始时&#xff…...

window-docker的容器使用宿主机音频设备

文章目录 前言操作配置 前言 你有没有遇到过这种情况&#xff1f; 你兴冲冲地在Windows上用Docker搭了个语音识别项目&#xff0c;准备让容器高歌一曲&#xff0c;或者至少"Hey Docker"一下。结果——静音。 Docker Desktop一脸无辜&#xff1a;“亲&#xff0c;默…...

NaVILA: Legged Robot Vision-Language-ActionModel for Navigation

摘要 本文旨在解决基于视觉与语言导航&#xff08;VLN&#xff09;在四足机器人上的实现问题。该任务不仅为人类提供了一种灵活的指令方式&#xff0c;还使机器人能够在更具挑战性和杂乱的场景中导航。然而&#xff0c;将人类自然语言指令转换为低层次的腿部关节控制指令并非易…...

LeetCode 2071 你可以安排的最多任务数目 题解(附带自己的错误做题思路 过了25/49)

示例 输入&#xff1a;tasks [3,2,1], workers [0,3,3], pills 1, strength 1 输出&#xff1a;3 解释&#xff1a; 我们可以按照如下方案安排药丸&#xff1a; - 给 0 号工人药丸。 - 0 号工人完成任务 2&#xff08;0 1 > 1&#xff09; - 1 号工人完成任务 1&#…...

高翔《视觉SLAM十四讲》中第13讲,单目稠密重建中的RMODE数据集

高翔《视觉SLAM十四讲》中第13讲&#xff0c;单目稠密重建&#xff0c;中的RMODE数据集&#xff0c; 原作者苏黎世大学slam小组提供&#xff0c;但是网址已失效 下载方式&#xff1a; 1 https://vj6cqktnxq.feishu.cn/wiki/KBqtwD6XJio3Rmkm2FkckMY8nPg 2 参考地址&#xff1a…...

PyTorch_张量形状操作

搭建模型时&#xff0c;数据都是基于张量形式的表示&#xff0c;网络层与层之间很多都是以不同的shape的方式进行表现和运算。 对张量形状的操作&#xff0c;以便能够更好处理网络各层之间的数据连接。 reshape 函数的用法 reshape 函数可以再保证张量数据不变的前提下改变数…...

【浅尝Java】变量与数据类型(含隐式类型转换、强制类型转换、整型与字符串互相转换等)

&#x1f35e;自我激励&#xff1a;每天努力一点点&#xff0c;技术变化看得见 文章目录 字面常量数据类型变量变量概念语法格式整型变量字节型变量&#xff08;byte&#xff09;短整型变量&#xff08;short&#xff09;整型变量&#xff08;int&#xff09;长整型&#xff08…...

Ubuntu环境下使用uWSGI服务器【以flask应用部署为例】

0、前置内容说明 首先要知道WSGI是什么&#xff0c;关于WSGI服务器的介绍看这篇&#xff1a;WSGI&#xff08;Web Server Gateway Interface&#xff09;服务器 由于从Python 3.11开始限制了在系统级 Python 环境中使用 pip 安装第三方包&#xff0c;以避免与系统包管理器&am…...

GCC 使用指南

安装 GCC Ubuntu/Debian: sudo apt update && sudo apt install gcc gCentOS/RHEL: sudo yum install gcc gcc-cmacOS (通过 Homebrew): brew install gcc基本用法 编译 C 程序 gcc hello.c -o hello # 编译 hello.c&#xff0c;生成可执行文件 hello ./hello …...

虚函数 vs 纯虚函数 vs 静态函数(C++)

&#x1f9e9; 一图看懂&#xff1a;虚函数 vs 纯虚函数 特性虚函数&#xff08;Virtual&#xff09;纯虚函数&#xff08;Pure Virtual&#xff09;语法virtual void foo();virtual void foo() 0;是否必须实现✅ 必须在类中实现❌ 不在基类实现&#xff0c;派生类必须实现是…...

CF1000E We Need More Bosses

CF1000E We Need More Bosses 题目描述 题目大意&#xff1a; 给定一个 n n n 个点 m m m 条边的无向图&#xff0c;保证图连通。找到两个点 s , t s,t s,t&#xff0c;使得 s s s到 t t t必须经过的边最多&#xff08;一条边无论走哪条路线都经过ta&#xff0c;这条边就是…...

Python:Seaborn 美化图表的技术指南

🎨 1、简述 Seaborn 是建立在 Matplotlib 基础上的高级可视化库,提供了更美观、更简洁的数据统计图表。本文将带你深入了解 Seaborn 的强大功能,并通过多个实践案例掌握使用技巧。 2、Seaborn 1️⃣ 什么是 Seaborn? Seaborn 是一个基于 matplotlib 构建的 Python 可视…...

go实现循环链表

需求 实现循环链表的节点生成、顺序遍历、指定删除。 实现 package mainimport ("fmt" )type zodiac_sign struct {number intdizhi stringanimal stringyear intnext *zodiac_sign }// 添加 // func add_node_by_order(previous_node zodiac_sign, current_…...

QT | 常用控件

前言 &#x1f493; 个人主页&#xff1a;普通young man-CSDN博客 ⏩ 文章专栏&#xff1a;C_普通young man的博客-CSDN博客 ⏩ 本人giee: 普通小青年 (pu-tong-young-man) - Gitee.com 若有问题 评论区见&#x1f4dd; &#x1f389;欢迎大家点赞&#x1f44d;收藏⭐文章 —…...

EasyExcel使用总结

EasyExcel 文章目录 EasyExcel1、导入1.1、基本方式导入1.导入依赖2. 加载源文件基本语法 3. 读取数据行4. 读取结果 1.2、模型映射导入1.定义实体映射类2. 操作读取基本语法 3. 读取数据行4. 读取结果 1.3、导入类型转换器语法 1.4、导入监听器基本语法&#xff1a; 1.5、多行…...

【形式化验证】动态逻辑(DL)的定义解释与示例

动态逻辑&#xff08;Dynamic Logic, DL&#xff09;是一种用于描述和验证程序行为的逻辑系统。它结合了命题逻辑、谓词逻辑以及模态逻辑的特点&#xff0c;特别适用于表达程序执行前后的状态变化。以下将从语法、语义以及实际应用等方面详细介绍DL公式的相关内容。 1. 动态逻…...

OpenCv实战笔记(1)在win11搭建opencv4.11.1 + qt5.15.2 + vs2019_x64开发环境

一. 准备工作 Visual Studio 2019&#xff08;安装时勾选 C 桌面开发 和 Windows 10 SDK&#xff09; CMake 3.20&#xff08;官网下载&#xff09; Qt 5.15.2&#xff08;下载 Qt Online Installer&#xff09;安装时勾选 MSVC 2019 64-bit 组件。 opencv 4.11.1 源码下载 git…...

四年级数学知识边界总结思考-上册

目录 一、背景二、过程1.大数的认识**一、知识点梳理****二、知识点的由来****三、作用与意义****四、总结** 2. 公顷和平方千米**一、知识点梳理****二、知识点的由来****三、作用与意义** 3.角的度量**一、知识点梳理****二、知识点的由来****三、作用与意义** 4.平行四边形和…...

(undone) MIT6.S081 2023 学习笔记 (Day10: LAB9 fs file system)

url: https://pdos.csail.mit.edu/6.1810/2023/labs/fs.html 任务1&#xff1a;Large files (moderate) ----------------- 完成 本次作业中&#xff0c;你将扩大xv6文件的最大容量。当前xv6文件被限制为268个块&#xff08;即268*BSIZE字节&#xff0c;xv6中BSIZE为1024&…...

SpringMVC详解

一&#xff1a;Maven 1.1 概述 &#xff08;1&#xff09;项目结构 所有IDE使用Maven创建的项目结构完全一样&#xff0c;maven项目可通用 &#xff08;2&#xff09;构建流程&#xff08;编译、测试、打包、发布&#xff09; &#xff08;3&#xff09;依赖管理 定义&#xff…...

【Python】一直没搞懂生成器是什么。。

生成器 上期我们讲解了迭代器:【Python】一直没搞懂迭代器是什么。。-CSDN博客 这期我们来讲讲它的好兄弟——生成器 生成器 (Generator)? 生成器是一种特殊的 迭代器 (Iterator)。 迭代器 是你可以逐个访问其元素的对象(比如在 for 循环中使用)。列表、元组、字典、字符…...

高等数学同步测试卷 同济7版 试卷部分 上 做题记录 第四章 不定积分同步测试卷 B卷

第四章 不定积分同步测试卷 B卷 一、单项选择题(本大题共5小题,每小题3分,总计15分) 1. 2. 3. 4. 5. 二、填空题(本大题共5小题,每小题3分,总计15分) 6. 7. 8. 9. 10. 三、求解下列各题(本大题共5小题,每小题6分,总计30分) 11. 12. …...

只用Prettier进行格式化项目

1.下载Prettier插件&#xff0c;禁用ESlint 2.在项目根目录新建.prettierrc文件 {"singleQuote": true,"jsxSingleQuote": true,"printWidth": 100,"trailingComma": "none","tabWidth": 2,"semi": f…...

ARM寻址方式

寻址方式指的是确定操作数位置的方式。 寻址方式&#xff1a; 立即数寻址 直接寻址&#xff08;绝对寻址&#xff09;&#xff0c;ARM不支持这种寻址方式&#xff0c;但所有CISC处理器都支持 寄存器间接寻址 3种寻址方式总结如下&#xff1a; 助记符 RTL格式 描述 ADD r0,r1…...

2025年- H25-Lc133- 104. 二叉树的最大深度(树)---java版

1.题目描述 2.思路 返回左右子树中&#xff0c;最高高度的子树,高度从0开始计数。 3.代码实现 class TreeNode {int val;TreeNode left;TreeNode right;TreeNode() {}TreeNode(int val) { this.val val; }TreeNode(int val, TreeNode left, TreeNode right) {this.val val;…...

深入理解 Spring MVC:DispatcherServlet 与视图解析机制​

import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Locale; import java.util.Map;// 继承自 FrameworkServlet 的 DispatcherServlet 类…...

Python基本语法(lambda表达式)

lambda表达式 lambda的一般形式是在关键字lambda后面跟一个或多个参数&#xff0c;之后再紧跟一个 冒号&#xff0c;接下来是一个表达式。lambda是一个表达式&#xff0c;而不是一个语句&#xff0c;它能够出现 在Python语法不允许def出现的地方。作为表达式&#xff0c;lambd…...

嵌入式按键原理、中断过程与中断程序设计(键盘扫描程序)

按键去抖动  通常的按键所用开关为机械弹性开关,当机械触点断开、闭合时&#xff0c;电压信号波型如下图。由于机械触点的弹性作用&#xff0c;一个按键开关在闭合时不会马上稳定地接通&#xff0c;在断开时也不会一下子断开。因而在闭合及断开的瞬间均伴随有一连串的抖动。…...

C++负载均衡远程调用学习之实时监测与自动发布功能

目录 1.LarsDns-V0.3BackenThread后端实时监控线程流程 2.LarsDns-V0.3加载当前Route版本号方法实现 3.LarsDns-V0.3加载RouteChange修改表的信息 4.LarsDns-V0.3实现实时监控流程线程业务 5.LarsDnsV0.3编译bug修改和功能测试 6.Lars Web管理界面的集成 7.LarsDnsV0.3 D…...

VSCode常用插件推荐

文章目录 VSCode常用插件推荐1 Git相关插件2 代码格式3 AI工具4 语言插件通用工具参考 VSCode常用插件推荐 1 Git相关插件 2 代码格式 3 AI工具 4 语言插件 通用工具 参考 50 个 VSCode 必装插件推荐 https://mp.weixin.qq.com/s/b_OKvg3hdavtnv7pbWcKWg...

性能优化实践:内存优化技巧

性能优化实践&#xff1a;内存优化技巧 在Flutter应用开发中&#xff0c;内存优化是提升应用性能的关键环节之一。本文将从实战角度深入探讨Flutter内存优化的各种技巧&#xff0c;帮助你构建高性能的Flutter应用。 一、内存分析工具使用 1. DevTools内存分析器 启动DevTool…...

WPF中Behaviors

行为的好处 可以把复杂的界面逻辑抽象出去&#xff0c;让xaml的界面设计更简单&#xff0c;更清爽 1.安装包 Microsoft.Xaml.Behaviors.Wpf2.简单实现拖动效果 <Border Width"100"Height"100"Background"Red"><i:Interaction.Behav…...

FreeRTOS菜鸟入门(十)·消息队列

目录 1. 基本概念 2. 数据存储 3. 运作机制 4. 阻塞机制 4.1 出队阻塞 4.2 入队阻塞 5. 操作示意图 5.1 创建队列 5.2 向队列发送第一个消息 5.3 向队列发送第二个消息 5.4 从队列读取消息 6. 消息队列控制块 7. 消息队列常用函数 7.1 消息队列创建…...

Day3:设置页面全局渐变线性渐变背景色uniapp壁纸实战

效果&#xff1a; 页面全局渐变线性渐变背景色会让这个设计更加有质感 想给页面加背景的时候&#xff0c;就给最外部的布局容器添加一个pageBg这样一个类别 接下来&#xff0c;我们就可以在之前写的common的公共的style里的common-style.css里改变它就行了 线性渐变&#xff1…...

Ray开源程序 是用于扩展 AI 和 Python 应用程序的统一框架。Ray 由一个核心分布式运行时和一组用于简化 ML 计算的 AI 库组成

​一、软件介绍 文末提供程序和源码下载 Ray开源程序 是用于扩展 AI 和 Python 应用程序的统一框架。Ray 由一个核心分布式运行时和一组用于简化 ML 计算的 AI 库组成 二、Ray AI 库的更多信息 数据&#xff1a;适用于 ML 的可扩展数据集训练&#xff1a;分布式训练Tune&…...

19、权限控制:分院帽系统——React 19 RBAC实现

一、分院帽的魔法本质 "RBAC是霍格沃茨城堡的智能分院帽&#xff0c;用角色编织的星轨矩阵阻隔黑魔法入侵&#xff01;" 魔法部安全司官员挥舞魔杖&#xff0c;角色-权限的量子纠缠态在空中交织成防护结界。 ——基于《国际魔法联合会》第7号安全协议&#xff0c;RB…...

P1802 5 倍经验日

P1802 5 倍经验日 - 洛谷 题目背景 复制Markdown &#xff5b;展开 进入IDE模式 现在乐斗有活动了&#xff01;每打一个人可以获得5倍经验&#xff01;absi2011却无奈的看着那一些比他等级高的好友&#xff0c;想着能否把他们干掉。干掉能拿不少经验的。 题目描述 现在abs…...