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

C++核心编程之类和对象---C++面向对象的三大特性--多态

目录

一、多态

1. 多态的概念

2.多态的分类:

1. 静态多态:

2. 动态多态:

 3.静态多态和动态多态的区别:

4.动态多态需要满足的条件:

4.1重写的概念:

4.2动态多态的调用:

二、多态

三、多态的深入剖析

四、利用多态写一个模拟计算器案例

1.普通方式写一个模拟计算器

2.利用多态的方式写一个计算器

五、纯虚函数和抽象类

抽象类特点:

六、利用多态的抽象类写一个饮品制作流程的案例

七、纯析构和纯虚析构

虚析构和纯虚析构的共性:

虚析构和纯虚析构的区别:

总结:

八、利用多态写一个组装电脑的案例


一、多态

1. 多态的概念

计算机程序运行时,相同的消息可能会送给多个不同的类别之对象,而系统可依据对象所属类别,引发对应类别的方法,而有不同的行为。简单来说,所谓多态意指相同的消息给予不同的对象会引发不同的动作。

多态也可定义为“一种将不同的特殊行为和单个泛化记号相关联的能力”。

多态可分为变量多态与函数多态。变量多态是指:基类型的变量(对于C++是引用或指针)可以被赋值基类型对象,也可以被赋值派生类型的对象。函数多态是指,相同的函数调用界面(函数名与实参表),传送给一个对象变量,可以有不同的行为,这视该对象变量所指向的对象类型而定。因此,变量多态是函数多态的基础。 

多态是c++面向对象的三大特性之一

2.多态的分类:

1. 静态多态:

      函数重载 和 运算符重载 属于静态多态,复用函数名

     静态多态(static polymorphism):模板也允许将不同的特殊行为和单个泛化记号相关联,由于这种关联处理于编译期而非运行期,因此被称为“静态”。可以用来实现类型安全、运行高效的同质对象集合操作。C++STL不采用动态多态来实现就是个例子。

  • 函数重载(Function Overloading)

  • 运算符重载(Operator Overloading)

  • 带变量的宏多态(macro polymorphism)

  • 非参数化多态或译作特设多态(Ad-hoc polymorphism):

  • 参数化多态(Parametric polymorphism):把类型作为参数的多态。在面向对象程序设计中,这被称作泛型编程。

2. 动态多态:

    派生类 和 虚函数 实现运行时多态

   动态多态(dynamic polymorphism):通过类继承机制和虚函数机制生效于运行期。可以优雅地处理异质对象集合,只要其共同的基类定义了虚函数的接口。也被称为子类型多态(Subtype polymorphism)或包含多态(inclusion polymorphism)。在面向对象程序设计中,这被直接称为多态。

对于C++语言,带变量的宏和函数重载(function overload)机制也允许将不同的特殊行为和单个泛化记号相关联。然而,习惯上并不将这种函数多态(function polymorphism)、宏多态(macro polymorphism)展现出来的行为称为多态(或静态多态),否则就连C语言也具有宏多态了。谈及多态时,默认就是指动态多态,而静态多态则是指基于模板的多态。

 3.静态多态和动态多态的区别:

        1. 静态多态的函数地址早绑定,编译阶段确定函数地址

        2. 动态多态的函数地址晚绑定,运行阶段确定函数地址

4.动态多态需要满足的条件:

        1.有继承关系

        2.子类中重写父类的虚函数(子类中写不写virtual都可以)

4.1重写的概念:

        函数返回值类型  函数名  参数列表都完全相同。

        注意:与函数重载要区分。

4.2动态多态的调用:

        父类的指针或引用  执行子类对象

二、多态

示例:

#include<iostream>using namespace std;// 多态// 动态多态的满足条件// 1. 有继承关系// 2. 子类要重写父类的虚函数// 动态多态的使用// 父类的指针或引用  指向子类对象// 动物类class Animal{public:// 虚函数virtual void speak(){cout<<"动物在说话"<<endl;}};// 猫类class Cat:public Animal{public:// 重写  函数返回值类型  函数名 参数列表要   完全相同void speak(){cout<<"猫在说话"<<endl;}};// 狗类class Dog:public Animal{public:void speak(){cout<<"狗在说话"<<endl;}};// 执行说话的函数void dospeak(Animal &animal) // Animal & animal  =  cat;{// 地址早绑定  在编译阶段确定函数地址// 如果要执行猫说话,那么这个函数地址就不能提前绑定// 需要在运行阶段进行绑定,地址晚绑定animal.speak();}// c++允许父类和子类的转化void test01(){Cat cat;// cat.speak();dospeak(cat);  // 父类的引用,接收的是子类的对象Dog dog;dospeak(dog);}int main(){test01();return 0;}

没写 virtual 之前是地址早绑定

写入虚函数后,地址晚绑定运行结果:

 

三、多态的深入剖析

图解示例:

示例:

#include<iostream>using namespace std;// 多态的底层逻辑// 动物类class Animal{public:// 虚函数void speak(){cout << "动物在说话" << endl;}};// 猫类class Cat :public Animal{public:// 重写  函数返回值类型  函数名 参数列表要   完全相同void speak(){cout << "猫在说话" << endl;}};// 狗类class Dog :public Animal{public:void speak(){cout << "狗在说话" << endl;}};// 执行说话的函数void dospeak(Animal& animal){// 地址早绑定  在编译阶段确定函数地址// 如果要执行猫说话,那么这个函数地址就不能提前绑定// 需要在运行阶段进行绑定,地址晚绑定animal.speak();}// c++允许父类和子类的转化void test01(){Cat cat;// cat.speak();dospeak(cat);  // 父类的引用,接收的是子类的对象Dog dog;dospeak(dog);}void test02(){cout << "Animal 类的大小:" << sizeof(Animal) << endl;}int main(){test01();test02();return 0;}

通过命令提示符查看

加入虚函数后

子类在没有重写的时候

子类重写虚函数后

没加virtual的类的大小,相当于空类,大小是1

变为虚函数后的类的大小为8/4(看你的编译器是多少位的),类的大小是一个指针的大小

关于命令提示符查看类可查询上一篇文章:命令提示符查看类

四、利用多态写一个模拟计算器案例

多态的优点:

  • 代码组织结构清晰
  • 可读性强
  • 利于前期和后期的扩展及维护

1.普通方式写一个模拟计算器

示例1:

#include<iostream>using namespace std;// 分别利用普通写法和多态的技术实现计算器的功能// 普通的写法class Calculator{public:int get_result(string oper){if(oper == "+")return m_num1+m_num2;if(oper == "-")return m_num1 - m_num2;if(oper == "*")return m_num1 * m_num2;if(oper == "/")return m_num1 / m_num2;}int m_num1;int m_num2;};void test01(){Calculator c;c.m_num1 = 40;c.m_num2 = 20;// 开闭原则,对扩展进行开放,对修改进行关闭cout<<c.m_num1<<" + "<<c.m_num2<<" = "<<c.get_result("+")<<endl;cout<<c.m_num1<<" - "<<c.m_num2<<" = "<<c.get_result("-")<<endl;cout<<c.m_num1<<" * "<<c.m_num2<<" = "<<c.get_result("*")<<endl;cout<<c.m_num1<<" / "<<c.m_num2<<" = "<<c.get_result("/")<<endl;}int main(){test01();return 0;}

运行结果:

2.利用多态的方式写一个计算器

示例2:

#include<iostream>using namespace std;// 利用多态实现计算器class Abstract_Calculator{public:virtual int get_result(){return 0;}int num1;int num2;};// 设计一个加法计算器的类class Add_Calculator:public Abstract_Calculator{public:int get_result(){return num1+num2;}};// 设计一个减法计算器的类class Sub_Calculator:public Abstract_Calculator{public:int get_result(){return num1-num2;}};// 设计一个乘法计算器的类class Mul_Calculator:public Abstract_Calculator{public:int get_result(){return num1*num2;}};void test02(){// 多态的使用条件// 父类的指针或引用指向子类对象// 加法运算Abstract_Calculator *abc = new Add_Calculator;abc->num1 = 100;abc->num2 = 200;cout<<abc->num1<<" + "<<abc->num2<<" = "<<abc->get_result()<<endl;// 堆区数据用完记得销毁delete abc;// 减法运算abc = new Sub_Calculator;abc->num1 = 200;abc->num2 = 100;cout<<abc->num1<<" - "<<abc->num2<<" = "<<abc->get_result()<<endl;delete abc;// 乘法运算abc = new Mul_Calculator;abc->num1 = 200;abc->num2 = 100;cout<<abc->num1<<" * "<<abc->num2<<" = "<<abc->get_result()<<endl;delete abc;}int main(){test02();return 0;}

运行结果:

五、纯虚函数和抽象类

在多态中,通常父类中虚函数的实现是毫无意义的,主要是调用子类的重写内容

因此可以将虚数改为纯虚数

纯虚数语法: virtual 返回值类型 函数名(参数列表) =  0 ;

当类中有了纯虚函数,这个类称为抽象类

抽象类特点:

  1. 无法实例化对象
  2. 子类必须重写抽象类中的纯虚函数,否则也属于抽象类

示例:

#include<iostream>using namespace std;// 纯虚数抽象类class Base{public:virtual void func() = 0; // 虚函数的基础上才可以等于0,纯虚函数// 只要有一个纯虚数,这个类称为抽象类};// 抽象类的子类,必须要重写父类中的纯虚函数,否则也是抽象类,无法实例化对象class Son:public Base{public:void func(){cout<<"func函数调用"<<endl;}};void test01(){// Base b; 无法实例化一个抽象类// new 一个也不行Base *base = new Son;base->func();}int main(){test01();return 0;}

运行结果:

六、利用多态的抽象类写一个饮品制作流程的案例

案例描述:利用多态技术,提供抽象类制作饮品基类,提供子类制作咖啡和茶叶

示例:

#include<iostream>using namespace std;class Abstract_Drinking{public:// 煮水virtual void Boil() = 0;// 冲泡virtual void Brew() = 0;// 倒入杯中virtual void Pour_Cup() = 0;// 加入辅助佐料virtual void Put_something() = 0;// 制作饮品void make_drink(){Boil();Brew();Pour_Cup();Put_something();}};// 具体的制作// 咖啡class Coffee:public Abstract_Drinking{public:// 煮水virtual void Boil(){cout<<"煮矿泉水"<<endl;}// 冲泡virtual void Brew(){cout<<"冲泡咖啡"<<endl;}// 倒入杯中virtual void Pour_Cup(){cout<<"倒入杯中"<<endl;}// 加入辅助佐料virtual void Put_something(){cout<<"加入糖和牛奶"<<endl;}};// 茶class Tea:public Abstract_Drinking{public:// 煮水virtual void Boil(){cout<<"煮矿泉水"<<endl;}// 冲泡virtual void Brew(){cout<<"冲泡茶叶"<<endl;}// 倒入杯中virtual void Pour_Cup(){cout<<"倒入杯中"<<endl;}// 加入辅助佐料virtual void Put_something(){cout<<"加入柠檬,枸杞"<<endl;}};// 制作void do_work(Abstract_Drinking * abd)// Abstract_Drinking *abd = new Coffee  父类指针指向子类对象{abd->make_drink();delete abd;// 在堆区制作完记得释放}void test01(){// 制作咖啡do_work(new Coffee);cout<<"-------------"<<endl;// 制作茶do_work(new Tea);}int main(){test01();return 0;}

运行结果:

七、纯析构和纯虚析构

问题:多态使用时,如果子类中有属性开辟到堆区,那么父类指针在释放时无法调用到子类的析构代码。

解决办法:将父类中的析构函数改为**虚析构**或者**纯虚析构**

虚析构和纯虚析构的共性:

  • 可以解决父类指针释放子类对象
  • 都需要有具体的函数实现

虚析构和纯虚析构的区别:

  • 如果是纯虚析构,该对象属于抽象类,无法实现实例化对象

**虚析构语法:**

virtual ~类名(){}

**纯虚析构语法:**

virtual ~类名()= 0;

类名::~类名(){} // 类内声明,类外实现

示例:

#include<iostream>using namespace std;// 虚析构和纯虚析构class Animal{public:Animal(){cout<<"Animal的构造函数的调用"<<endl;}virtual void speak() = 0;// 变为纯虚函数// 利用虚析构可以解决  父类指针释放子类对象时不干净的问题/*virtual ~Animal(){cout<<"Animal虚析构函数的调用"<<endl;}*/virtual ~Animal() = 0;// 纯虚析构// 需要声明  也需要实现// 有了纯虚析构之后,那么这个类也属于抽象类,无法实现实例化对象};Animal::~Animal(){cout<<"Animal纯虚析构函数的调用"<<endl;}class Cat: public Animal{public:Cat(string name){cout<<"这是Cat的构造函数的调用"<<endl;this->name = new string(name);}void speak(){cout<<*name<<"小猫在说话"<<endl;}~Cat(){if(this->name!=NULL){cout<<"这是Cat的析构函数的调用"<<endl;delete this->name;this->name = NULL;}}string *name;// 创建在堆区};void test01(){Animal *animal = new Cat("Tom");animal->speak();// 父类的指针在析构的时候不会调用子类的析构函数// 导致子类如果在堆区有数据,会出现内存泄漏的情况delete animal;}int main(){test01();return 0;}

运行结果:

总结:

  1. 虚析构或纯虚析构就是用来解决通过父类指针释放子类对象
  2. 如果子类中没有堆区数据,可以不写为虚析构或者纯虚析构
  3. 拥有纯虚析构函数的类也属于抽象类

八、利用多态写一个组装电脑的案例

案例说明:

电脑主要组成部件为CPU(用于计算),显卡〔用于显示),内存条〔用于存储)

将每个零件封装出抽象基类,并且提供不同的厂商生产不同的霉件,例如Intel厂商和Lenovo厂商

创建电脑类提供让电脑工作的函数,并且调用每个零件工作的接口

测试时组装三台下同的电脑进行工作

示例:

#include<iostream>using namespace std;// 抽象不同零件的类// 计算机类class CPU{public:// 抽象的计算函数virtual void calculate() = 0;};// 显卡类class Video_Card{public:// 抽象的显示函数virtual void display() = 0;};// 内存条类class Memory{public:// 抽象的存储函数virtual void storage() = 0;};// 提供电脑类class Computer{public:Computer(CPU* cpu, Video_Card* vc, Memory* mem){this->cpu = cpu;this->vc = vc;this->mem = mem;}// 提供工作函数void work(){// 让零件工作起来,调用接口this->cpu->calculate();this->vc->display();this->mem->storage();}// 提供析构函数  释放在堆区创建的三个零件~Computer(){if(cpu!=NULL){delete cpu;cpu = NULL;}if(vc!=NULL){delete vc;vc = NULL;}if(mem!=NULL){delete mem;mem = NULL;}}private:CPU* cpu;  // CPU的零件指针Video_Card* vc;  // 显卡的零件指针Memory* mem;  // 内存条的零件指针};// 具体厂商// Intel厂商// CPUclass Intel_CPU :public CPU{public:void calculate(){cout << "这是Intel厂商的CPU,并且开始计算了" << endl;}};// 显卡class Intel_Video_Card :public Video_Card{public:void display(){cout << "这是Intel厂商的显卡,并且开始显示了" << endl;}};// 内存条class Intel_Memory :public Memory{void storage(){cout << "这是Intel厂商的内存条,并且开始存储了" << endl;}};// Lenovo厂商// CPUclass Lenovo_CPU :public CPU{public:void calculate(){cout << "这是Lenovo厂商的CPU,并且开始计算了" << endl;}};// 显卡class Lenovo_Video_Card :public Video_Card{public:void display(){cout << "这是Lenovo厂商的显卡,并且开始显示了" << endl;}};// 内存条class Lenovo_Memory :public Memory{void storage(){cout << "这是Lenovo厂商的内存条,并且开始存储了" << endl;}};void test01(){cout<<"------------------------"<<endl;cout<<"第一台电脑开始工作"<<endl;// 创建第一台电脑的零件CPU* intel_CPU = new Intel_CPU;Video_Card* intel_videocard = new Intel_Video_Card;Memory* intel_memory = new Intel_Memory;// 创建电脑零件的时候时在堆区创建的// 创建第一台电脑Computer* computer1 = new Computer(intel_CPU, intel_videocard, intel_memory);computer1->work();delete computer1;cout<<"-----------------------"<<endl;cout<<"第二台电脑开始工作"<<endl;// 组装第二台电脑Computer* computer2 = new Computer(new Lenovo_CPU, new Lenovo_Video_Card, new Lenovo_Memory);computer2->work();delete computer2;cout<<"-----------------------"<<endl;cout<<"第三台电脑开始工作"<<endl;// 组装第三台电脑Computer* computer3 = new Computer(new Lenovo_CPU, new Intel_Video_Card, new Lenovo_Memory);computer3->work();delete computer3;}int main(){test01();return 0;}

运行结果:

相关文章:

C++核心编程之类和对象---C++面向对象的三大特性--多态

目录 一、多态 1. 多态的概念 2.多态的分类&#xff1a; 1. 静态多态&#xff1a; 2. 动态多态&#xff1a; 3.静态多态和动态多态的区别&#xff1a; 4.动态多态需要满足的条件&#xff1a; 4.1重写的概念&#xff1a; 4.2动态多态的调用&#xff1a; 二、多态 三、多…...

基于PyQT的图片批处理系统

项目背景&#xff1a; 随着数字摄影技术的普及&#xff0c;人们拍摄和处理大量图片的需求也越来越高。为了提高效率&#xff0c;开发一个基于 PyQt 的图片批处理系统是很有意义的。该系统可以提供一系列图像增强、滤波、水印、翻转、放大缩小、旋转等功能&#xff0c;使用户能够…...

vscode文件配置

lanuch.json {"version": "0.2.0","configurations": [{"name": "(gdb) 启动","type": "cppdbg","request": "launch",// "program": "输入程序名称&#xff0c;例…...

C++学习笔记——SLT六大组件及头文件

目录 一、C中STL&#xff08;Standard Template Library&#xff09; 二、 Gun源代码开发精神 三、 实现版本 四、GNU C库的头文件分布 bits目录 ext目录 backward目录 iostream目录 stdexcept目录 string目录 上一篇文章&#xff1a; C标准模板库&#xff08;STL&am…...

Spring之AOP源码(二)

书接上文 文章目录 一、简介1. 前文回顾2. 知识点补充 二、ProxyFactory源码分析1. ProxyFactory2. JdkDynamicAopProxy3. ObjenesisCglibAopProxy 三、 Spring AOP源码分析 一、简介 1. 前文回顾 前面我们已经介绍了AOP的基本使用方法以及基本原理&#xff0c;但是还没有涉…...

VS code console.log快捷键设置 :console.log(‘n>>>‘,n)

vscode设置log快捷显示&#xff1a; 一、打开 VS Code&#xff0c;并进入菜单栏选择 “文件”&#xff08;File&#xff09;-> “首选项”&#xff08;Preferences&#xff09;-> “用户代码片段”&#xff08;User Snippets&#xff09;。 二、在弹出的下拉菜单中选择 …...

ZooKeeper 简介

1、概念介绍 ZooKeeper 是一个开放源码的分布式应用程序协调服务&#xff0c;为分布式应用提供一致性服务的软件&#xff0c;由雅虎创建&#xff0c;是 Google Chubby 的开源实现&#xff0c;是 Apache 的子项目&#xff0c;之前是 Hadoop 项目的一部分&#xff0c;使用 Java …...

rke2 Online Deploy Rancher v2.8.0 latest (helm 在线部署 rancher v2.8.0)

文章目录 1. 简介2. 预备条件3. 安装 helm4. 安装 cert-manager4.1 yaml 安装4.2 helm 安装 5. 安装 rancher6. 验证7. 界面预览 1. 简介 Rancher 是一个 Kubernetes 管理工具&#xff0c;让你能在任何地方和任何提供商上部署和运行集群。 Rancher 可以创建来自 Kubernetes 托…...

k8s实战从入门到上天系列第一篇:K8s微服务实战内容开篇介绍

前言 我们使用开源ruoyi微服务基本使用&#xff0c;基于基本的微服务实践。我们来讲解k8s的实战内容。 第一章&#xff1a;开源ruoyi微服务简介基本使用 第二章&#xff1a;k8s基本知识回顾、k3s集群搭建和基本使用 第三章&#xff1a;微服务镜像构建 第四章&#xff1a;中间件…...

统一网关 Gateway【微服务】

文章目录 1. 前言2. 搭建网关服务3. 路由断言工厂4. 路由过滤器4.1 普通过滤器4.2 全局过滤器4.3 过滤器执行顺序 5. 跨域问题处理 1. 前言 通过前面的学习我们知道&#xff0c;通过 Feign 就可以向指定的微服务发起 http 请求&#xff0c;完成远程调用。但是这里有一个问题&am…...

【征服redis1】基础数据类型详解和应用案例

博客计划 &#xff0c;我们从redis开始&#xff0c;主要是因为这一块内容的重要性不亚于数据库&#xff0c;但是很多人往往对redis的问题感到陌生&#xff0c;所以我们先来研究一下。 本篇&#xff0c;我们先看一下redis的基础数据类型详解和应用案例。 1.redis概述 以mysql为…...

【WPF.NET开发】WPF中的XAML资源

本文内容 使用 XAML 中的资源静态和动态资源静态资源动态资源样式、DataTemplate 和隐式键 资源是可以在应用中的不同位置重复使用的对象。 资源的示例包括画笔和样式。 本概述介绍如何使用 Extensible Application Markup Language (XAML) 中的资源。 你还可以使用代码创建和…...

ChatGPT 淘金潮(全)

原文&#xff1a;The ChatGPT GoldRush 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 一、ChatGPT 简介 什么是 ChatGPT&#xff1f; ChatGPT 是由 OpenAI 基于 GPT-4 架构创建的大型语言模型。它旨在理解和回应自然语言文本输入&#xff0c;使得可以与机器进行对话…...

【零基础入门Python数据分析】Anaconda3 JupyterNotebookseaborn版

目录 一、安装环境 python介绍 anaconda介绍 jupyter notebook介绍 anaconda3 环境安装 解决JuPyter500&#xff1a;Internal Server Error问题-CSDN博客 Jupyter notebook快捷键操作大全 二、Python基础入门 数据类型与变量 数据类型 变量及赋值 布尔类型与逻辑运算…...

C++面试:单例模式、工厂模式等简单的设计模式 创建型、结构型、行为型设计模式的应用技巧

理解和能够实现基本的设计模式是非常重要的。这里&#xff0c;我们将探讨两种常见的设计模式&#xff1a;单例模式和工厂模式&#xff0c;并提供一些面试准备的建议。 目录 单例模式 (Singleton Pattern) 工厂模式 (Factory Pattern) 面试准备 1. 理解设计模式的基本概念…...

Oracle JDK 8 中的 computeIfAbsent 方法及实践

Java 8 引入了一系列新特性&#xff0c;其中之一是对 Map 接口的增强&#xff0c;其中包括了 computeIfAbsent 方法。这个方法为处理映射提供了一种便捷而强大的方式&#xff0c;允许在键不存在或对应的值为 null 时&#xff0c;动态计算新的值并将其放入映射。在本篇博客中&am…...

华为设备vlan下配置MSTP,STP选举

核心代码,不同实例&#xff0c;承载不同流量&#xff0c;为每个实例设置一个根网桥达到分流的效果 stp region-config //进入stp区域的设置 region-name R1 //区域命名为R1 instance 1 vlan 10 …...

案例学Python:filter()函数的用法,高级!

大家好&#xff0c;这里是程序员晚枫&#xff0c;又来分享有用的Python知识了。 Python之所以好用&#xff0c;是因为有大量用于科学计算的内置函数和第三方库。用好这些第三方库&#xff0c;可以显著提高我们编程的速度和质量。 今天我们一起来看一下Python中一个重要的内置…...

jmeter--7.BeanShell

目录 1. beanshell常用语法 1.1 log&#xff1a;日志写入 1.2 vars&#xff1a;设置和引用局部变量&#xff08;同线程组&#xff09; 1.3 props&#xff1a;设置和引用全局变量&#xff08;跨线程组&#xff09; 1.4 prev&#xff1a;获取前一个请求返回的信息 2. beans…...

第 3 场 蓝桥杯小白入门赛 解题报告 | 珂学家 | 单调队列优化的DP + 三指针滑窗

前言 整体评价 T5, T6有点意思&#xff0c;这场小白入门场&#xff0c;好像没真正意义上的签到&#xff0c;整体感觉是这样。 A. 召唤神坤 思路: 前后缀拆解 #include <iostream> #include <algorithm> #include <vector> using namespace std;int main()…...

12.找到字符串中所有字母异位词

&#x1f9e0; 题目解析 题目描述&#xff1a; 给定两个字符串 s 和 p&#xff0c;找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义&#xff1a; 若两个字符串包含的字符种类和出现次数完全相同&#xff0c;顺序无所谓&#xff0c;则互为…...

Springboot社区养老保险系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;社区养老保险系统小程序被用户普遍使用&#xff0c;为方…...

VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP

编辑-虚拟网络编辑器-更改设置 选择桥接模式&#xff0c;然后找到相应的网卡&#xff08;可以查看自己本机的网络连接&#xff09; windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置&#xff0c;选择刚才配置的桥接模式 静态ip设置&#xff1a; 我用的ubuntu24桌…...

使用Spring AI和MCP协议构建图片搜索服务

目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式&#xff08;本地调用&#xff09; SSE模式&#xff08;远程调用&#xff09; 4. 注册工具提…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解

在 C/C 编程的编译和链接过程中&#xff0c;附加包含目录、附加库目录和附加依赖项是三个至关重要的设置&#xff0c;它们相互配合&#xff0c;确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中&#xff0c;这些概念容易让人混淆&#xff0c;但深入理解它们的作用和联…...

【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制

使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下&#xff0c;限制某个 IP 的访问频率是非常重要的&#xff0c;可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案&#xff0c;使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...

腾讯云V3签名

想要接入腾讯云的Api&#xff0c;必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口&#xff0c;但总是卡在签名这一步&#xff0c;最后放弃选择SDK&#xff0c;这次终于自己代码实现。 可能腾讯云翻新了接口文档&#xff0c;现在阅读起来&#xff0c;清晰了很多&…...

论文阅读笔记——Muffin: Testing Deep Learning Libraries via Neural Architecture Fuzzing

Muffin 论文 现有方法 CRADLE 和 LEMON&#xff0c;依赖模型推理阶段输出进行差分测试&#xff0c;但在训练阶段是不可行的&#xff0c;因为训练阶段直到最后才有固定输出&#xff0c;中间过程是不断变化的。API 库覆盖低&#xff0c;因为各个 API 都是在各种具体场景下使用。…...

tomcat指定使用的jdk版本

说明 有时候需要对tomcat配置指定的jdk版本号&#xff0c;此时&#xff0c;我们可以通过以下方式进行配置 设置方式 找到tomcat的bin目录中的setclasspath.bat。如果是linux系统则是setclasspath.sh set JAVA_HOMEC:\Program Files\Java\jdk8 set JRE_HOMEC:\Program Files…...

基于鸿蒙(HarmonyOS5)的打车小程序

1. 开发环境准备 安装DevEco Studio (鸿蒙官方IDE)配置HarmonyOS SDK申请开发者账号和必要的API密钥 2. 项目结构设计 ├── entry │ ├── src │ │ ├── main │ │ │ ├── ets │ │ │ │ ├── pages │ │ │ │ │ ├── H…...