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

C++面向对象三大特征之一 ——(多态)

C++面向对象三大特征之一 ——多态

  • 一. 多态的概念
  • 二. 多态的定义及实现
    • 2.1多态的构成条件
    • 2.2 虚函数
    • 2.3虚函数的重写
      • 虚函数重写的两个例外:
    • 2.4 C++11 override 和 final
    • 2.5 重载、覆盖(重写)、隐藏(重定义)的对比
  • 三. 抽象类
    • 接口继承和实现继承
  • 四.多态的原理
    • 4.1虚函数表
  • 虚函数表存储在内存中的哪里
    • 4.2多态的原理
    • 4.3 动态绑定与静态绑定
  • 练题

一. 多态的概念

多态的概念:同一个方法或操作在不同的对象上可以有不同的表现或实现方式。简而言之,多态允许不同的对象以相同的方式响应相同的消息(方法调用),但是它们的行为却可能不同。多态让相同的接口具有不同的实现,提升了代码的复用性和扩展性。
例如:动物的叫声,狗是汪汪,猫是喵喵,同样都是叫声,发出的声音却不同。

二. 多态的定义及实现

2.1多态的构成条件

多态是在不同继承关系的类对象,去调用同一函数,产生了不同的行为
构成多态有两个条件:

  1. 必须通过基类的指针或者引用调用虚函数
  2. 被调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写

虚函数构成重写的要求:函数名,返回值,参数相同。

如下代码:

#include<iostream>
using namespace std;class Animal
{
public:virtual void sound(){cout << "sound" << endl;}
private:
};class Dog :public Animal
{
public:virtual void sound(){cout << "旺旺" << endl;}
private:string name = "";
};class Cat :public Animal
{
public:virtual void sound(){cout << "喵喵" << endl;}
private:string name = "";
};void AnimalSound(Animal& anm)
{anm.sound();
}int main()
{Animal a;Dog d;Cat c;AnimalSound(a);AnimalSound(d);AnimalSound(c);return 0;
}

输出结果:
在这里插入图片描述

2.2 虚函数

virtual 修饰的成员函数就是虚函数

class Animal
{
public:virtual void sound(){cout << "sound" << endl;}
};

2.3虚函数的重写

虚函数的重写(覆盖)派生类中有一个跟基类完全相同的虚函数(即派生类虚函数与基类虚函数的返回值类型、函数名字、参数列表完全相同),称子类的虚函数重写了基类的虚函数。

class Animal
{
public:virtual void sound(){cout << "sound" << endl;}
private:
};class Dog :public Animal
{
public:virtual void sound(){cout << "旺旺" << endl;}
};void AnimalSound(Animal& anm)
{anm.sound();
}int main()
{Animal a;Dog d;AnimalSound(a);AnimalSound(d);return 0;
}

这样写构成多态,AnimalSound函数可以输出对应动物的叫声。

但我们依然可以使函数只输出 sound(这是动物的叫声,看函数的定义) ,那就是指定类域,因为重写属于特殊的重定义(隐藏)。
在这里插入图片描述

虚函数重写的两个例外:

  1. 协变:虚函数的返回值可以不同,但返回值的类型必须是父类与子类的关系
class A {};
class B : public A {};class Animal
{
public:virtual A* f(){cout << "virtual A* f()" << endl;return new A;}
};class Dog :public Animal
{
public:virtual B* f(){cout << "virtual B* f()" << endl;return new B;}
};void fun(Animal& anm)
{anm.f();
}int main()
{Animal a;Dog d;fun(a);fun(d);return 0;
}

在这里插入图片描述

  1. 析构函数的重写(基类与派生类析构函数的名字不同)
class Animal
{
public:~Animal(){cout << "~Animal()" << endl;}
};class Dog :public Animal
{
public:~Dog(){cout << "~Dog()" << endl;}
};int main()
{Animal* panm = new Dog;delete panm;return 0;
}

这段程序不加 virtual 会导致内存泄漏
在这里插入图片描述
没有 virtual 修饰的析构函数它不构成多态,new申请的是 Dog 类,delete释放时只释放了DogAnimal部分

之前继承章节说过,继承的析构函数会先释放自己的那一部分,再调用父类的析构,释放父类的那一部分部分(且父类的析构我们不能显示的调用,必须由编译器自己调用)
所以我们现在的目的是让析构调到Dog(子类)里去。

在这里插入图片描述

上面说过构成多态的条件是:构成重写;必须是基类的指针或引用调用,重写的条件又是:函数名,返回值,参数相同。

父类和子类的函数名很明显不相同,但它们加上virtual后构成多态。
原因:为编译器对析构函数的名称做了特殊处理,编译后析构函数的名称统一处理成destructor

加上 virtual 后可以正确调用析构函数。
在这里插入图片描述

2.4 C++11 override 和 final

C++对函数重写的要求比较严格,但是有些情况下由于疏忽,可能会导致函数名字母次序写反而无法构成重载,而这种错误在编译期间是不会报出的,只有在程序运行时没有得到预期结果才来debug会得不偿失,因此:C++11提供了override和final两个关键字,可以帮助用户检测是否重写

override 检查函数是否被重写,如果没有重写则会报错

class Animal
{
public:void sound(){cout << "sound" << endl;}
};class Dog :public Animal
{
public:virtual void sound() override{cout << "旺旺" << endl;}
};

在这里插入图片描述
final 修饰的函数不能被重写,如果重写了就会报错

在这里插入图片描述
这样设计的意义是上面呢?
既然写了 virtual 那就说明函数可能会被重写,但又写了 final 不让函数被重写。
如下使用场景:

class Animal {
public:virtual void sound() {std::cout << "Animal sound" << std::endl;}
};class Dog : public Animal 
{
public:void sound() override final{std::cout << "Bark" << std::endl;}
};class Bulldog : public Dog 
{
public:// 这行会报错,因为 `sound` 在 Dog 中是 final,不能在 Bulldog 中重写void sound() override {std::cout << "Loud Bark" << std::endl;}
};

在这里插入图片描述

final 修饰的类 不可以被继承

class Animal final
{
public:virtual void sound() {std::cout << "Animal sound" << std::endl;}
};class Dog : public Animal 
{
public:void sound() override {std::cout << "Bark" << std::endl;}
};

在这里插入图片描述

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

在这里插入图片描述

三. 抽象类

在虚函数的后面写上 =0 ,则这个函数为纯虚函数。包含纯虚函数的类叫做抽象类(也叫接口类),抽象类不能实例化出对象。派生类继承后也不能实例化出对象,只有重写纯虚函数,派生类才能实例化出对象纯虚函数规范了派生类必须重写,另外纯虚函数更体现出了接口继承。

class Animal
{
public:virtual void sound() = 0{cout << "sound" << endl;}
};class Dog :public Animal
{
public:virtual void sound(){cout << "旺旺" << endl;}
};void AnimalSound(Animal& anm)
{anm.sound();
}int main()
{Animal a;Dog d;AnimalSound(d);return 0;
}

在这里插入图片描述
因为Animal 包含纯虚函数,所以它是抽象类,无法实例化出对象
在这里插入图片描述

接口继承和实现继承

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

四.多态的原理

4.1虚函数表

先计算下面程序的输出结果

class A
{
public:virtual void fun1(){}virtual void fun2(){}
private:int _a;
};class B
{
public:virtual void fun3(){}private:int _b;int _c;
};int main()
{cout << sizeof(A) << endl;cout << sizeof(B) << endl;return 0;
}

在这里插入图片描述

输出结果:
8
12
发现两个类都多了四字节的大小
实际上是因为虚函数导致多了四个字节的大小
当一个类中有虚函数时,这个类就会生成一个指针,指针向虚函数表,虚函数表中存放的是这个类中每个虚函数的地址。所以sizeof计算大小时会多出4个字节(多出一个指针的大小)
虚函数表中存的是虚函数的地址,那虚函数表本身是一个函数指针数组
类中自动生成的指针指向虚函数表,它的类型是函数指针数组指针,
下面画图+代码讲解

有如下代码:

B类继承A类
B类中重写了 fun1()函数class A
{
public:virtual void fun1(){}virtual void fun2(){}void fun3(){}private:int _a = 0;
};class B:public A
{
public:virtual void fun1(){}private:int _b = 0;int _c = 0;
};int main()
{A a;B b;return 0;
}

通过调试窗口查看,自动生成的指向虚函数表的指针:_vfptr
在这里插入图片描述

先看a对象:这里的 _vfptr 就是自动生成的指针,它指向了虚函数表,虚函数表中有两个元素(这两个元素是指针),指针分别指向虚函数 fun1() ,fun2() , fun3() 不是虚函数,所以不在虚函数表中。

再看b对象:b中包含了a对象,b中的a的 _vfptr 中也有两个元素,第一个元素是B类中重写后fun1() 的地址,第二个元素是 A类中fun2() 的地址,所以看到上图中的a对象的 _vfptr 的第二个元素与 b对象中A类部分的 _vfptr 的第二个元素的地址相同。

再声明一个 aa 对象,如下:

int main()
{A a;A aa;B b;return 0;
}

在这里插入图片描述
这里的 aaa 的虚表的地址相同。证明了用同一个类 声明出来的所有对象用的都是同一个虚表

总结一下派生类的虚表生成:

  1. 先将基类中的虚表内容拷贝一份到派生类虚表中
  2. 如果派生类重写了基类中某个虚函数,用派生类自己的虚函数覆盖虚表中基类的虚函数
  3. 派生类自己新增加的虚函数按其在派生类中的声明次序增加到派生类虚表的最后。

虚函数表存储在内存中的哪里

class A
{
public:virtual void fun1(){cout << "a::virtual void fun1()" << endl;}virtual void fun2(){}void fun3(){cout << "a::void fun3()" << endl;}private:int _a = 0;
};class B:public A
{
public:virtual void fun1(){cout << "b::virtual void fun1()" << endl;}private:int _b = 0;int _c = 0;
};void fun(A& ra)
{//动态绑定ra.fun1();//静态绑定ra.fun3();
}int main()
{int i = 0;static int j = 1;int* p1 = new int;const char* p2 = "xxxxxxxx";printf("栈:%p\n", &i);printf("静态区:%p\n", &j);printf("堆:%p\n", p1);printf("常量区:%p\n", p2);A a;B b;printf("A虚表地址:%p\n", *((int*)&a));printf("B虚表地址:%p\n", *((int*)&b));printf("A对象地址:%p\n", &a);printf("B对象地址:%p\n", &b);return 0;
}

在这里插入图片描述
虚函数表的地址与常量区接近,所以虚函数表和普通函数,虚函数一样都存在常量区(代码段),虚函数表在编译阶段生成

4.2多态的原理

class A
{
public:virtual void fun1(){cout << "A::virtual void fun1()" << endl;}virtual void fun2(){}void fun3(){cout << "A::void fun3()" << endl;}private:int _a = 0;
};class B:public A
{
public:virtual void fun1(){cout << "B::virtual void fun1()" << endl;}private:int _b = 0;int _c = 0;
};void fun(A& ra)
{ra.fun1();ra.fun3();
}int main()
{A a;B b;fun(a);fun(b);return 0;
}

输出结果
在这里插入图片描述
b是如何调用到它自己类中的函数的呢?
在这里插入图片描述

就是上面讲到的虚函数表。
在这里插入图片描述
下图中的引用可以理解为,引用的是子类中的父类部分,它会把虚函数表带过去。(指针也是同理)
在这里插入图片描述

由上图可以看出
多态的实现就是由虚函数表来完成的。
通过指针或引用来调用虚函数:

  1. 通过对象直接调用虚函数,C++会直接调用对象的相应函数版本,不会发生多态。
  2. 只有当通过基类的指针或引用调用虚函数时,C++才能实现动态绑定(即运行时多态),从而根据对象的实际类型调用正确的虚函数版本。

4.3 动态绑定与静态绑定

动态绑定:运行时绑定,虚函数。
静态绑定:编译时绑定,普通函数。
在这里插入图片描述
通过汇编代码,可以更清楚的看到虚函数是在运行时绑定的。

  1. 静态绑定又称为前期绑定(早绑定),在程序编译期间确定了程序的行为,也称为静态多态
    比如:函数重载
  2. 动态绑定又称后期绑定(晚绑定),是在程序运行期间,根据具体拿到的类型确定程序的具体行为,调用具体的函数,也称为动态多态
  3. 对象访问普通函数快还是虚函数更快?答:首先如果是普通对象,是一样快的。如果是指针对象或者是引用对象,则调用的普通函数快,因为构成多态,运行时调用虚函数需要到虚函数表中去查找。

练题

下面代码输出的是什么

class A 
{
public:virtual void func(int val = 1) {  // 默认参数是 1std::cout << "A->" << val << std::endl;}virtual void test() {func();  // 默认参数 1}
};class B : public A 
{
public:void func(int val = 0) override {  // 默认参数是 0std::cout << "B->" << val << std::endl;}
};int main() 
{B* p = new B;p->test();  // 调用 A::test()return 0;
}

解析:
p是指向B对象的指针,因为B继承了A,B中没有test(),就会调到A中的test()
test(),中又调用func(),func()函数有virtual修饰构成多态。
所以输出是 B->0 ???
答案是B->1
在这里插入图片描述
因为C++中的重写,它只重写函数体,不会重写函数头。
所以是A中的函数头 virtual void func(int val = 1)
B中的函数体
{
std::cout << “B->” << val << std::endl;
}

相关文章:

C++面向对象三大特征之一 ——(多态)

C面向对象三大特征之一 ——多态 一. 多态的概念二. 多态的定义及实现2.1多态的构成条件2.2 虚函数2.3虚函数的重写虚函数重写的两个例外&#xff1a; 2.4 C11 override 和 final2.5 重载、覆盖(重写)、隐藏(重定义)的对比 三. 抽象类接口继承和实现继承 四.多态的原理4.1虚函数…...

HTTP协议及安全防范

由于图片解析问题&#xff0c;可以点击查看 &#x1f449;&#x1f3fb; 博客原文 HTTP&#xff08;Hypertext Transfer Protocol&#xff09;超文本传输协议是一个用于 Web 应用程序通信的应用层协议。它是一种客户端-服务器协议&#xff0c;客户端通过发送请求到服务器来获取…...

JVM简介—1.Java内存区域

1.运行时数据区的介绍 (1)运行时数据区的定义 Java虚拟机在执行Java程序的过程中&#xff0c;会把它所管理的内存划分为若干个不同的数据区域&#xff0c;这些区域各有各的用途以及各自的创建和销毁时间也不一样。有的区域会随着虚拟机的进程启动而存在&#xff0c;有的区域则依…...

IPC协议获取签名信息

一&#xff1a;IPC协议获取签名信息详解 目录 什么是IPC协议&#xff1f;签名信息概述IPC协议中签名信息获取的流程相关知识点 数字签名原理常见签名算法数据完整性与认证签名的生成与验证IPC中的安全传输 应用场景总结 什么是IPC协议&#xff1f; IPC&#xff08;Inter-Pro…...

高校就业管理系统:数据驱动的就业服务创新

1 Java语言 Java语言是目前最流行的语言之一&#xff0c;不仅可以做桌面窗口形式的程序&#xff0c;还可以做浏览器访问的程序&#xff0c;目前最流行的就是用Java语言作为基础&#xff0c;做各种程序的后台处理。Java语言是操作变量的语言&#xff0c;而变量则是Java对于数据存…...

C++中的模板元编程

模板元编程 模板特化&#xff1a; 指的是对某个特定类型或特定类型组合提供模板的定制实现。 示例&#xff1a; #include<iostream> using namespace std;template <typename T> void func(T t) {cout << "Generic template: " << t <…...

rk3568制冷项目驱动开发流程汇总(只适用于部分模块CIF DVP等,自用)

采用fpga输入&#xff0c;3568采集并显示至hdmi RKVICAP 驱动框架说明 RKVICAP驱动主要是基于 v4l2 / media 框架实现硬件的配置、中断处理、控制 buffer 轮转&#xff0c;以及控制 subdevice(如 mipi dphy 及 sensor) 的上下电等功能。 对于RK356X 芯片而言&#xff0c; VICAP…...

EMC——射频场感应的传导骚扰抗扰度(CS)

术语和定义 AE&#xff08;辅助设备&#xff09; 为受试设备正常运行提供所需信号的设备和检验受试设备性能的设备&#xff1b; 钳注入 是用电缆上的钳合式“电流”注入装置获得的钳注入&#xff1b; 电流钳 由被注入信号的电缆构成的二次绕组实现的电流变换器&#xff1b; 电磁…...

postgreSql对分钟级的降雨数据进行插值为整小时

postgreSql对分钟级的降雨数据进行插值为整小时 SQL语句实现 SQL语句实现 --核查某个小流域的降雨量小时插值是否正确SELECT tm, sum(drp) as sum, round(sum(drp), 2) as drp2 from(SELECT a.stcd, (TO_TIMESTAMP(time_period, YYYY-MM-DD HH24:MI:SS) INTERVAL 1 HOUR) as t…...

如何安全获取股票实时数据API并在服务器运行?

以下是安全获取股票实时数据 API 并在服务器运行的方法&#xff1a; 选择合适的券商或交易平台 评估自身需求&#xff1a;明确自己的交易策略、交易品种、交易频率等需求&#xff0c;以及对 股票api 的功能、性能、稳定性等方面的要求。调研券商或平台&#xff1a;了解不同券商…...

Android Bootable Recovery 中的 `imgdiff.cpp` 文件解析

Android Bootable Recovery 中的 imgdiff.cpp 文件解析 引言 在 Android 系统中,Recovery 模式是一个非常重要的组成部分,它允许用户在设备无法正常启动时进行系统修复、数据恢复、OTA 更新等操作。其中,OTA(Over-The-Air)更新是 Android 系统中常见的更新方式,它通过网…...

golang学习笔记-变量与常量

1.标识符 在编程语言中标识符就是程序员定义的具有特殊意义的词,比如变量名,常量名,函数名等.go语言中标识符有字母数字和_(下划线)组成,并且只能以字母和_开头 2.关键字 关键字是指变成语言中预先定义好的特殊含义的标识符 break default func interface select case …...

关于变分量子算法的问答

1.零噪声外推如何通过增加误差的过程来改善估计的误差缓解类型? 解释&#xff1a;**零噪声外推&#xff08;ZNE&#xff09;**是一种误差缓解方法&#xff0c;通过故意增加噪声并利用这些增加噪声的结果来改进量子电路的估计。其核心思想是在不同的噪声级别下运行量子电路&am…...

小学数学思维训练 一年级 第一周(少儿思维启蒙)

前言 本文主要介绍了通过各种题型和解题方法培养孩子的数学思维能力。通过系统的方法训练一年级学生的数学思维能力&#xff0c;帮助他们学会举一反三&#xff0c;融会贯通地解决各类数学问题。 点击获取小学数学1-6年级思维训练电子版 第一周 比一比 比一比是实际生活中常…...

sqlite 自定以脚本解释器

应用程序使用 libfdt 解析设备树,获取兼容性配置 内核源码支持libfdt 标准设备树语法,不用自己再创造 非常的爽,因为设备树支持预编译 一些可以跑类 BSD 系统的设备也可以使用这样的方法,不仅仅是在linux 系统上跑 有pylibfdt 支持解析设备树&#xff0c;校验设备树是否是正确的…...

动手学深度学习11.2. 凸性-笔记练习(PyTorch)

本节课程地址&#xff1a;72 优化算法【动手学深度学习v2】_哔哩哔哩_bilibili 本节教材地址&#xff1a;11.2. 凸性 — 动手学深度学习 2.0.0 documentation 本节开源代码&#xff1a;...>d2l-zh>pytorch>chapter_multilayer-perceptrons>convexity.ipynb 凸性 …...

go并发模型的详细介绍

Go 语言的并发模型是其一大亮点&#xff0c;它使得并发编程变得简单高效。Go 语言并发模型的核心概念是 goroutines 和 channels。在理解这两个概念之前&#xff0c;我们首先了解并发编程的一些基本概念。 1. 并发与并行 并发&#xff08;Concurrency&#xff09;&#xff1a;…...

使用FreeNAS软件部署ISCSI的SAN架构存储(IP-SAN)练习题

一&#xff0c;实验用到工具分别为&#xff1a; VMware虚拟机&#xff0c;安装教程&#xff1a;VMware Workstation Pro 17 安装图文教程 FreeNAS系统&#xff0c;安装教程&#xff1a;FreeNAS-11.2-U4.1安装教程2024&#xff08;图文教程&#xff09; 二&#xff0c;新建虚…...

FreeSWITCH实现多人电话会议功能

FreeSWITCH实现多人电话会议功能 作者&#xff1a;基于Java与FreeSWITCH的开源呼叫中心系统FreeIPCC FreeSWITCH作为一个开源的电话软交换平台&#xff0c;为企业和运营商提供了构建高效、灵活的语音通信系统的能力。其中&#xff0c;多人电话会议功能是其核心应用之一&#…...

Chromium 中chrome.webRequest扩展接口定义c++

一、chrome.webRequest 注意&#xff1a;从 Manifest V3 开始&#xff0c;"webRequestBlocking"权限不再适用于大多数扩展程序。以"declarativeNetRequest"为例&#xff0c;它允许使用declarativeNetRequest API。除了"webRequestBlocking"之外…...

极乐 15.2.6 | 清爽版简约美观音乐软件,支持网易云歌单导入

极乐是一款使用起来非常轻松的音乐播放软件&#xff0c;它拥有清新简洁的画面&#xff0c;专注于音乐播放功能。最新版本全面升级了64位架构&#xff0c;带来了前所未有的性能提升和更稳定的体验。通过优化内存管理&#xff0c;降低了应用对系统资源的占用&#xff0c;确保设备…...

如何在 Ubuntu 22.04 上安装 Graylog 开源日志管理平台

简介 Graylog 的开源特性、丰富的功能、灵活性和可扩展性使其成为一个流行的日志管理平台。在本教程中&#xff0c;我将向你展示如何在 Ubuntu 22.04 上安装 Graylog&#xff0c;包括配置 Graylog 服务器软件包和访问 Graylog Web UI。 Graylog 是什么&#xff1f; Graylog …...

Wux weapp 组件库的 bug—— wux-picker选择器组件无法正确初始化到选定的value

options的value为Number&#xff0c;组件无法正常使用 解决方案&#xff0c;修改picker-view/utils.js中的getIndexFromValue函数&#xff0c;如下&#xff1a; export function getIndexFromValue(value, col [], fieldNames DEFAULT_FIELD_NAMES) {//return getRealIndex(…...

决策树(理论知识1)

目录 何为决策树决策树的组成决策树的构建 何为决策树 决策树(Decision Tree)是一种分类和回归方法&#xff0c;是基于各种情况发生的所需条件构成决策树&#xff0c;以实现期望最大化的一种图解法。由于这种决策 分支画成图形很像一棵树的枝干&#xff0c;故称决策树。它的运…...

【Spring】获取Bean对象需要哪些注解

阿华代码&#xff0c;不是逆风&#xff0c;就是我疯 你们的点赞收藏是我前进最大的动力&#xff01;&#xff01; 希望本文内容能够帮助到你&#xff01;&#xff01; 目录 一&#xff1a;Service&#xff08;服务存储&#xff09; 1&#xff1a;存储bean的代码 2&#xff1…...

java的Webclient对象怎解解析400状态码

在Java中使用WebClient处理400状态码&#xff0c;可以通过检查响应状态并根据状态码进行相应的错误处理。以下是几种处理400状态码的方法&#xff1a; 使用onStatus方法判断和处理错误&#xff1a; 你可以使用WebClient的retrieve()方法链中的onStatus方法来检查响应状态码。如…...

【计算机视觉基础CV-图像分类】03-深度学习图像分类实战:鲜花数据集加载与预处理详解

本文将深入介绍鲜花分类数据集的加载与处理方式&#xff0c;同时详细解释代码的每一步骤并给出更丰富的实践建议和拓展思路。以实用为导向&#xff0c;为读者提供从数据组织、预处理、加载到可视化展示的完整过程&#xff0c;并为后续模型训练打下基础。 前言 在计算机视觉的深…...

ubuntu 如何重装你的apt【apt-get报错: symbol lookup error/undefined symbol】

副标题:解决error:apt-get: symbol lookup error: /lib/x86_64-linux-gnu/libapt-private.so.0.0: undefined symbol: _ZNK13pkgTagSection7FindULLENS_3KeyERKy, version APTPKG_6.0 文章目录 问题描述报错分析解决方案:重装你的apt1、查看你的ubuntu版本2、下载适配你的ap…...

Unity 上好用的插件

PlayerMaker BehaviorDesigner Cinemachine Timeline Hybrid Addressable AssetBundle Blower Simple Zoom 大地图上缩放和平移使用ScrollRect的好效果实现...

大数据机器学习算法和计算机视觉应用07:机器学习

Machine Learning Goal of Machine LearningLinear ClassificationSolutionNumerical output example: linear regressionStochastic Gradient DescentMatrix Acceleration Goal of Machine Learning 机器学习的目标 假设现在有一组数据 x i , y i {x_i,y_i} xi​,yi​&…...

Godot RPG 游戏开发指南

Godot RPG 游戏开发指南 一、基础准备 1. 开发环境 下载并安装最新版 Godot 4.x选择使用 GDScript 或 C# 作为开发语言准备基础美术资源&#xff08;角色、地图、道具等&#xff09; 2. 项目结构 project/ ├── scenes/ # 场景文件 ├── scripts/ # 脚…...

c++ 找第一个只出现一次的字符

【题目描述】 给定一个只包含小写字母的字符串&#xff0c;请你找到第一个仅出现一次的字符。如果没有&#xff0c;输出no。 【输入】 一个字符串&#xff0c;长度小于100000。 【输出】 输出第一个仅出现一次的字符&#xff0c;若没有则输出no。 【输入样例】 abcabd【输出样…...

时空信息平台架构搭建:基于netty封装TCP通讯模块(IdleStateHandler网络连接监测,处理假死)

文章目录 引言I 异步TCP连接操作II 心跳机制:空闲检测(读空闲和写空闲)基于Netty的IdleStateHandler类实现心跳机制(网络连接监测)常规的处理假死健壮性的处理假死方案获取心跳指令引言 基于netty实现TCP客户端:封装断线重连、连接保持 https://blog.csdn.net/z92911896…...

【Rust自学】3.6. 控制流:循环

3.6.0. 写在正文之前 欢迎来到Rust自学的第三章&#xff0c;一共有6个小节&#xff0c;分别是: 变量与可变性数据类型&#xff1a;标量类型数据类型&#xff1a;复合类型函数和注释控制流&#xff1a;if else控制流&#xff1a;循环&#xff08;本文&#xff09; 通过第二章…...

如何正确计算显示器带宽需求

1. 对显示器的基本认识 一个显示器的参数主要有这些&#xff1a; 分辨率&#xff1a;显示器屏幕上像素点的总数&#xff0c;通常用横向像素和纵向像素的数量来表示&#xff0c;比如19201080&#xff08;即1080p&#xff09;。 刷新率&#xff1a;显示器每秒钟画面更新的次数&…...

mysql 基于chunk机制是如何支持运行期间,动态调整buffer pool大小的

mysql 基于chunk机制是如何支持运行期间&#xff0c;动态调整buffer pool大小的 MySQL 的 InnoDB 存储引擎确实支持在运行期间动态调整缓冲池&#xff08;buffer pool&#xff09;的大小&#xff0c;但其机制与自定义缓存系统有所不同。InnoDB 通过内部优化和配置参数来实现这…...

梳理你的思路(从OOP到架构设计)_简介设计模式

目录 1、 模式(Pattern) 是较大的结构​编辑 2、 结构形式愈大 通用性愈小​编辑 3、 从EIT造形 组合出设计模式 1、 模式(Pattern) 是较大的结构 组合与创新 達芬奇說&#xff1a;簡單是複雜的終極形式 (Simplicity is the ultimate form of sophistication) —Leonardo d…...

【Redis】缓存

什么是缓存 https://tech.meituan.com/2017/03/17/cache-about.html Spring Data Redis Spring Data Redis提供了从Spring应用程序轻松配置和访问Redis的功能。 引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>sp…...

基于 PyCharm 和 Navicat 的新闻管理系统

# 用于创建连接池 pip3 install mysql-connector-python # 改变终端打印颜色 pip3 install colorama 1.创建连接池 文件地址&#xff1a;db/mysql_db.py 首先建立一个与 MySQL 数据库的连接池&#xff0c;以便在应用程序中复用连接&#xff0c;提高性能。 如果连接池创建失败…...

<QNAP 453D QTS-5.x> 日志记录: 优化性能 内存管理 修改swap优先顺序 swap放在ssd 网络稳定性 进程出错管理

起因 几个月前&#xff0c;开始重学编程&#xff0c;往 NAS 的 docker 里放了些 containers &#xff0c;每一个用来跑练习的 App。为了放更多的app&#xff0c;上个月加了 4GB 内存。最近只放了两个&#xff0c;NAS 就会时不时的闪断。codes 全存在网络驱动器上&#xff0c;当…...

一区牛顿-拉夫逊算法+分解+深度学习!VMD-NRBO-Transformer-GRU多变量时间序列光伏功率预测

一区牛顿-拉夫逊算法分解深度学习&#xff01;VMD-NRBO-Transformer-GRU多变量时间序列光伏功率预测 目录 一区牛顿-拉夫逊算法分解深度学习&#xff01;VMD-NRBO-Transformer-GRU多变量时间序列光伏功率预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.中科院一区…...

本地部署webrtc应用怎么把http协议改成https协议?

环境&#xff1a; WSL2 Ubuntu22.04 webrtc视频聊天应用 问题描述&#xff1a; 本地部署webrtc应用怎么把http协议改成https协议&#xff1f; http协议在安卓手机浏览器上用不了麦克风本&#xff0c;来地应用webrtc 本来是http协议&#xff0c;在安卓手机上浏览器不支持使…...

React简单了解

原理简化了解 import React from "react" import { createRoot } form "react-dom/client"const element React.createElement(p,{id: hello},Hello World! )const container document.querySelector(#root) const root createRoot(container) root.r…...

基于LabVIEW的USRP信道测量开发

随着无线通信技术的不断发展&#xff0c;基于软件无线电的设备&#xff08;如USRP&#xff09;在信道测量、无线通信测试等领域扮演着重要角色。通过LabVIEW与USRP的结合&#xff0c;开发者可以实现信号生成、接收及信道估计等功能。尽管LabVIEW提供了丰富的信号处理工具和图形…...

Docker挂载

目录 数据卷挂载 本地目录挂载 数据卷挂载 宿主机默认的存放所有容器数据卷的目录&#xff1a;/var/lib/docker/volumes nginx容器 静态文件目录&#xff1a;/usr/share/nginx/html 配置文件目录&#xff1a;/etc/nginx/nginx.conf 修改宿主机的内容&#xff0c;进入到容器查…...

使用Java结合经纬度位置计算目标点的日出日落时间

目录 前言 一、应用示例 1、天安门升旗时间 2、湖南省日出日落信息 二、JAVA日出日落计算 1、在线API 2、使用Java进行计算 三、总结 前言 随着城市化进程的加速&#xff0c;城市环境与人类生活的联系日益紧密。城市不仅承载着居住、工作、休闲等多种功能&#xff0c;也…...

八字精批api接口_php获取生成八字和批注的方法研究

八字算命 API 介绍 这个八字算命 API 提供了一种便捷的方式&#xff0c;让用户通过 GET 或 POST 请求获取详细的八字信息。API 返回的数据格式为 JSON&#xff0c;包含多种命理分析和建议&#xff0c;适合对传统命理学感兴趣的用户。 API 功能 五行分析&#xff1a; 提供用户…...

docker run 命令参数

user docker run -it --nameubn18 --gpus all --privilegedtrue --shm-size 8G ubuntu:18.04 /bin/bash-it 是什么意思 4o 在运行 docker run 命令时&#xff0c;-it 是两个选项的组合&#xff0c;用于更好地与容器进行交互&#xff1a; -i 或 --interactive&#xff1a;这个选…...

智能外呼技术如何改变企业营销方式

智能外呼技术如何改变企业营销方式 作者&#xff1a;开源大模型智能呼叫中心系统FreeAICC&#xff0c;Github&#xff1a;https://github.com/FreeIPCC/FreeAICC 在数字化时代&#xff0c;企业营销方式正经历着前所未有的变革。其中&#xff0c;智能外呼技术作为一项前沿的人…...

redis数据转移

可能有时候因为硬件的原因我们我们需要更换服务器&#xff0c;如果更换服务器的话&#xff0c;那我们redis的数据该怎样转移呢&#xff0c;按照一下步骤即可完成redis数据的转移 1.进入redis客户端 2.使用 bgsave命令进行数据的备份&#xff0c;此命令完成后会在你的redis安装目…...