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

C++入门——12继承

1.继承

继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。以前我们接触的复用都是函数复用,继承是类设计层次的复用。

class Person
{
public:void Print(){cout << "name:" << _name << endl;cout << "age:" << _age << endl;}
protected:string _name = "peter"; // 姓名int _age = 18;  // 年龄
};// 继承后父类的Person的成员(成员函数+成员变量)都会变成子类的一部分。这里体现出了Student和Teacher复用了Person的成员。class Student : public Person{protected:int _stuid; // 学号
};class Teacher : public Person
{
protected:int _jobid; // 工号
};int main()
{Student s;Teacher t;s.Print();t.Print();return 0;
}//name:peter
//age:18
//name:peter
//age:18

2 继承的定义

2.1格式

Person是父类,也称作基类。Teacher是子类,也称作派生类。

2.2继承关系和访问限定符

类成员/继承方式public继承protected继承private继承
基类的public成员派生类的public成员派生类的protected 成员派生类的private 成员
基类的protected 成员派生类的protected成员派生类的protected 成员派生类的private 成员
基类的private成 员在派生类中不可见在派生类中不可见在派生类中不可见
  • 基类 private 成员的访问

    • 基类中的 private 成员在派生类中确实是不可见的。无论继承方式如何,这些成员对派生类都是不可访问的。
    • 如果需要在派生类中访问这些成员,可以通过基类提供 protectedpublic 方法间接访问,或者在基类中提供友元类或友元函数。
  • 基类 protected 成员的访问

    • 基类中的 protected 成员在派生类中是可访问的,允许派生类访问和修改这些成员,但它们在派生类外部仍然不可见。
    • protected 成员的访问权限是为了支持派生类访问,限制了直接外部访问。
  • 继承方式与访问控制

    • 基类的 private 成员在子类中是不可见的,protected 成员在子类中可见。实际访问方式取决于基类成员的访问修饰符和继承方式的组合。
    • 继承方式(publicprotectedprivate)会影响基类成员在派生类中的访问级别。通常,public 继承使基类的 public 成员保持 publicprotected 继承使基类的 publicprotected 成员都变为 protectedprivate 继承则使基类的所有 publicprotected 成员都变为 private
  • 默认继承方式

    • class 默认使用 private 继承。
    • struct 默认使用 public 继承。
    • 明确指定继承方式可以提高代码的可读性和维护性,避免由于默认继承方式带来的混淆。
  • 继承的使用建议

    • 在实际编程中,public 继承是最常用的,因为它能够支持广泛的代码复用和接口设计。
    • protectedprivate 继承通常用于更特殊的场景,比如在实现某些设计模式时。protected 继承可以防止外部代码直接使用基类的接口,而 private 继承则主要用于实现内部细节的封装。

2.3实例演示三种继承关系下基类成员的各类型成员访问关系的变化

class Person
{
public :void Print (){cout<<_name <<endl;}protected :string _name ; // 姓名private :int _age ; // 年龄
};
  • public 继承
class Student : public Person
{
protected:int _stunum; // 学号
};Student s;
s.Print(); // 可以访问
// s._name; // 不可访问,编译错误
// s._age; // 不可访问,编译错误
  • protected 继承
class Student : protected Person
{
protected:int _stunum; // 学号
};Student s;
// s.Print(); // 不可访问,编译错误
// s._name; // 不可访问,编译错误
// s._age; // 不可访问,编译错误
  • private 继承
  • class Student : private Person
    {
    protected:int _stunum; // 学号
    };Student s;
    // s.Print(); // 不可访问,编译错误
    // s._name; // 不可访问,编译错误
    // s._age; // 不可访问,编译错误

    3.基类和派生类对象赋值转换

  • 派生类对象可以赋值基类的对象 / 基类的指针 / 基类的引用。这里有个形象的说法叫切片或者切割。寓意把派生类中父类那部分切来赋值过去。
  • 基类对象不能赋值给派生类对象。
  • 基类的指针或者引用可以通过强制类型转换赋值给派生类的指针或者引用。但是必须是基类的指针是指向派生类对象时才是安全的。这里基类如果是多态类型,可以使用RTTI(Run-Time Type Information)的dynamic_cast 来进行识别后进行安全转换。

3.1. 对象切片(Object Slicing)

  • 当派生类对象赋值给基类对象时,只有派生类中的基类部分会被复制,这个过程称为“切片”。
  • 切片后的基类对象不再包含派生类独有的数据和行为,只保留基类部分的内容。
class Base {
public:int baseVar;
};class Derived : public Base {
public:int derivedVar;
};Derived d;
d.baseVar = 1;
d.derivedVar = 2;Base b = d;  // 切片,Base 对象只保留 baseVar,丢失 derivedVar

3.2. 基类对象不能赋值给派生类对象

基类对象不包含派生类的所有信息,因此无法赋值给派生类对象。这会导致派生类独有的成员无法初始化或被错误地初始化。

3.3指针和引用的类型转换

向上转换(Upcasting)派生类的指针或引用可以赋值给基类的指针或引用。这是安全的,因为派生类总是包含基类的部分。

Derived* d = new Derived();
Base* b = d;  // 向上转换

向下转换(Downcasting):基类的指针或引用可以通过强制类型转换赋值给派生类的指针或引用,但前提是这个基类指针或引用实际指向的是派生类的对象,否则会导致未定义行为。

  • 在多态情况下,可以使用 dynamic_cast 进行向下转换,并通过 RTTI 确保转换的安全性:
Base* b = new Derived();  //这个基类指针或引用实际指向的是派生类的对象
Derived* d = dynamic_cast<Derived*>(b);  // 安全的向下转换if (d != nullptr) {// 转换成功,可以安全使用 d
}
  • RTTI(Run-Time Type Information):C++ 提供了 dynamic_cast 来在运行时检查和转换类型。dynamic_cast 只能用于多态类型(即至少有一个虚函数的类),它会在类型不匹配时返回 nullptr

4.继承中的作用域

4.1. 独立的作用域

  • 在 C++ 中,基类和派生类各自拥有独立的作用域。这意味着即使在派生类中定义了与基类同名的成员,它们也属于不同的作用域。
  • 由于作用域不同,在派生类中定义的同名成员会“隐藏”基类的成员,这种隐藏可以通过显式指定作用域来解决

4.2. 成员隐藏(Name Hiding)

  • 当子类和父类有同名成员时,子类的成员会隐藏父类的同名成员。这种隐藏机制适用于成员变量和成员函数。
  • 访问隐藏成员如果需要访问被隐藏的基类成员,可以使用 基类名::成员名 的形式来访问
     
    class Base {
    public:int value = 10;void display() { cout << "Base display" << endl; }
    };class Derived : public Base {
    public:int value = 20;  // 隐藏了 Base::valuevoid display() { cout << "Derived display" << endl; }  // 隐藏了 Base::display()
    };Derived d;
    cout << d.value << endl;          // 输出 20,访问的是 Derived::value
    cout << d.Base::value << endl;    // 输出 10,访问的是 Base::valued.display();                      // 输出 "Derived display"
    d.Base::display();                // 输出 "Base display"
    

4.3. 成员函数的隐藏

  • 成员函数的隐藏仅仅依赖于函数名是否相同,而不考虑参数列表(即使参数列表不同,基类的函数依然会被隐藏)。
  • 这种情况在函数重载和继承结合时容易导致混淆,因此在派生类中重新定义基类函数时需要特别小心。

4.4. 避免同名成员

  • 在实际开发中,尽量避免在继承体系中定义同名成员,尤其是函数和变量。这不仅可以减少隐藏问题,也可以提升代码的可读性和维护性。

5.派生类的默认成员函数

5.1. 构造函数

  • 在派生类的构造函数中,必须先调用基类的构造函数来初始化基类部分。如果基类没有默认构造函数,必须在派生类的初始化列表中显式调用基类的构造函数。
class Base {
public:Base(int x) : value(x) {}
protected:int value;
};class Derived : public Base {
public:Derived(int x, int y) : Base(x), derivedValue(y) {}
protected:int derivedValue;
};

5.2. 拷贝构造函数

  • 派生类的拷贝构造函数会调用基类的拷贝构造函数,以确保基类部分被正确复制。
Derived(const Derived& other) : Base(other), derivedValue(other.derivedValue) {}

5.3. 赋值运算符 operator=

  • 派生类的赋值运算符必须调用基类的赋值运算符来处理基类部分的赋值。通常是在派生类的赋值操作中先调用基类的赋值运算符,然后再处理派生类自身的数据成员。
Derived& operator=(const Derived& other) {if (this != &other) {Base::operator=(other); // 调用基类的赋值运算符derivedValue = other.derivedValue;}return *this;
}

5.4. 析构函数

  • 派生类的析构函数在执行完派生类的清理工作后,自动调用基类的析构函数,确保基类部分也被正确清理。这种顺序确保资源的释放顺序与分配顺序相反。
~Derived() {// 派生类的清理工作// 自动调用基类的析构函数
}

5.5. 构造和析构顺序

  • 构造函数的调用顺序是:先调用基类构造函数,再调用派生类构造函数。
  • 析构函数的调用顺序则相反:先调用派生类析构函数,再调用基类析构函数。

5.6. 析构函数的隐藏与重写

  • 如果基类析构函数没有声明为 virtual,派生类的析构函数会隐藏基类的析构函数。这意味着通过基类指针删除派生类对象时,只有基类部分会被释放,可能导致资源泄露。因此,如果类可能作为基类使用,析构函数通常应声明为 virtual
class Base {
public:virtual ~Base() {} // 推荐用法
};class Derived : public Base {
public:~Derived() {} // 派生类析构函数
};

6.继承与友元

  • 友元关系不受继承方式的影响,友元函数和友元类可以访问被友元声明类的所有成员。基类的友元函数或友元类不能访问派生类的私有或受保护成员,除非在派生类中重新声明它们为友元。友元关系在继承层次中是不可传递的。
#include <iostream>
using namespace std;class Student;  // 前向声明class Person {
public:Person(const string& name = "") : _name(name) {}friend void Display(const Person& p, const Student& s);  // 友元函数声明
protected:string _name;  // 姓名
};class Student : public Person {
public:Student(const string& name = "", int stuNum = 0) : Person(name), _stuNum(stuNum) {}
protected:int _stuNum;  // 学号
};void Display(const Person& p, const Student& s) {cout << "Name: " << p._name << endl;cout << "Student Number: " << s._stuNum << endl;
}int main() {Person p("Alice");Student s("Bob", 12345);Display(p, s);return 0;
}

7.继承与静态成员

基类定义了static静态成员,则整个继承体系里面只有一个这样的成员。无论派生出多少个子
类,都只有一个static成员实例 。

#include <iostream>
using namespace std;class Person {
public:Person() { ++_count; }  // 构造函数中增加计数static int _count;     // 静态数据成员声明
protected:string _name;         // 姓名
};int Person::_count = 0;  // 静态数据成员定义class Student : public Person {
protected:int _stuNum;          // 学号
};class Graduate : public Student {
protected:string _seminarCourse; // 研究科目
};void TestPerson() {Student s1;Student s2;Student s3;Graduate s4;// 输出人数cout << "人数: " << Person::_count << endl;  //4// 注意: 直接访问和修改 Person::_count 是有效的,因为静态数据成员是共享的// Student::_count = 0;  // 这行代码实际上不影响 Person::_count,因为静态数据成员是共享的// 重置静态数据成员 (这行代码将 Person::_count 设置为0)Person::_count = 0;// 输出人数cout << "人数: " << Person::_count << endl;  //0
}  int main() {TestPerson();return 0;
}

8.复杂的菱形继承及菱形虚拟继承

单继承:一个子类只有一个直接父类时称这个继承关系为单继承

多继承:一个子类有两个或以上直接父类时称这个继承关系为多继承

菱形继承:菱形继承是多继承的一种特殊情况。

菱形继承的问题:从下面的对象成员模型构造,可以看出菱形继承有数据冗余和二义性的问题。
在Father的对象中Person成员会有两份。

class Person
{
public :string _name ; // 姓名
};class Student : public Person
{
protected :int _num ; //学号
};
class Teacher : public Person
{
protected :int _id ; // 职工编号
};class Father : public Student, public Teacher
{
protected :string _childname ; // 孩子名字
};
void Test ()
{// 这样会有二义性无法明确知道访问的是哪一个Father a ;a._name = "peter";// 需要显示指定访问哪个父类的成员可以解决二义性问题,但是数据冗余问题无法解决a.Student::_name = "xxx";a.Teacher::_name = "yyy";
}

虚拟继承可以解决菱形继承的二义性和数据冗余的问题。如上面的继承关系,在Student和Teacher的继承Person时使用虚拟继承,即可解决问题。需要注意的是,虚拟继承不要在其他地方去使用。

class Person
{
public :string _name ; // 姓名
};class Student : virtual public Person
{
protected :int _num ; //学号
};class Teacher : virtual public Person
{
protected :int _id ; // 职工编号
};class father : public Student, public Teacher
{
protected :string _childname ; 
};
void Test ()
{Assistant a ;a._name = "peter";
}

8.1虚拟继承解决数据冗余和二义性的原理

在内存中,A的内存地址会在D后面,这里B和C的两个指针,指向的一张表。这两个指针叫虚基表指针,这两个表叫虚基表。虚基表中存的偏移量。通过偏移量可以找到下面的A。

9.继承vs组合

  • 继承(is-a)每个派生类对象都是一个基类对象。:

    • 特点:派生类是基类的一种类型,继承基类的接口和实现。继承实现了类的复用,但可能会破坏基类的封装。
    • 优点:简单直接,适合实现明确的“是一个”关系。例如,CatAnimal 的一种。
    • 缺点:耦合度高,基类的变化可能影响到所有派生类。继承可能导致复杂的继承层次结构(如菱形继承)。
#include <iostream>
#include <string>
using namespace std;class Shape {
public:Shape(const string& color) : _color(color) {}virtual void draw() const = 0; // 纯虚函数,强制子类实现
protected:string _color; // 颜色属性
};class Circle : public Shape {
public:Circle(const string& color, double radius): Shape(color), _radius(radius) {}void draw() const override {cout << "Drawing a " << _color << " circle with radius " << _radius << endl;}
private:double _radius;
};class Rectangle : public Shape {
public:Rectangle(const string& color, double width, double height): Shape(color), _width(width), _height(height) {}void draw() const override {cout << "Drawing a " << _color << " rectangle with width " << _width << " and height " << _height << endl;}
private:double _width, _height;
};int main() {Circle c("red", 5.0);Rectangle r("blue", 4.0, 6.0);c.draw();r.draw();return 0;
}
  • 组合(has-a)假设B组合了A,每个B对象中都有一个A对象:

    • 特点:类通过包含其他类的对象来实现功能,强调“有一个”关系。组合对象的内部细节对外部是隐藏的。
    • 优点:低耦合度,组合对象的变化不会影响到其他类。组合支持更灵活的设计,符合“黑箱复用”原则。
    • 缺点:组合可能需要更多的代码来实现对象之间的协调和交互。
#include <iostream>
#include <string>
using namespace std;class Color {
public:Color(const string& color) : _color(color) {}string getColor() const { return _color; }
private:string _color;
};class Shape {
public:Shape(const Color& color) : _color(color) {}virtual void draw() const = 0; // 纯虚函数,强制子类实现
protected:Color _color; // 通过组合来管理颜色
};class Circle : public Shape {
public:Circle(const Color& color, double radius): Shape(color), _radius(radius) {}void draw() const override {cout << "Drawing a " << _color.getColor() << " circle with radius " << _radius << endl;}
private:double _radius;
};class Rectangle : public Shape {
public:Rectangle(const Color& color, double width, double height): Shape(color), _width(width), _height(height) {}void draw() const override {cout << "Drawing a " << _color.getColor() << " rectangle with width " << _width << " and height " << _height << endl;}
private:double _width, _height;
};int main() {Color red("red");Color blue("blue");Circle c(red, 5.0);Rectangle r(blue, 4.0, 6.0);c.draw();r.draw();return 0;
}
  • 则设计原
    • 优先使用组合:组合提供了更多的灵活性和更低的耦合度。通过组合,你可以创建更复杂的对象而不依赖于继承体系的复杂性。
    • 合理使用继承:当类之间存在明确的“is-a”关系,并且继承不会导致过度的耦合和复杂性时,继承是合适的选择。继承在实现多态和共享行为时是必要的。
    • 理解封装:组合支持更好的封装,因为对象的内部实现对外部是隐藏的,而继承可能暴露了基类的内部实现。

相关文章:

C++入门——12继承

1.继承 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段&#xff0c;它允许程序员在保持原有类特性的基础上进行扩展&#xff0c;增加功能&#xff0c;这样产生新的类&#xff0c;称派生类。继承呈现了面向对象程序设计的层次结构&#xff0c;体现了由简…...

Python做统计图之美

Python数据分析可视化 案例效果图 import pandas as pd import matplotlib.pyplot as plt import matplotlib# 数据 data {"房型": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],"住宅类型": ["普通宅", "普通宅", "普通宅", &q…...

激光雷达点云投影到图像平面

将激光雷达点云投影到图像平面涉及几何变换和相机模型的应用。以下是该过程的基本原理&#xff1a; 1. 坐标系转换 激光雷达生成的点云通常位于激光雷达的坐标系中&#xff0c;而图像则在相机坐标系中。为了将点云投影到图像上&#xff0c;首先需要将点云从激光雷达坐标系转换…...

[python]将anaconda默认创建环境python版本设置为32位的

首先看看gpt怎么回答的 装了Anaconda。如果尚未安装&#xff0c;可以从Anaconda官网下载适合你的操作系统的安装程序&#xff0c;并按照安装向导进行安装。 二、创建32位Python环境 在Anaconda中&#xff0c;你可以通过修改环境变量来尝试切换到32位模式&#xff08;尽管这并…...

Jmeter+Influxdb+Grafana平台监控性能测试过程(三种方式)

一、Jmeter自带插件监控 下载地址&#xff1a;Install :: JMeter-Plugins.org 安装&#xff1a;下载后文件为jmeter-plugins-manager-1.3.jar&#xff0c;将其放入jmeter安装目录下的lib/ext目录&#xff0c;然后重启jmeter&#xff0c;即可。 启动Jmeter&#xff0c;测试计…...

[创业之路-135] :ERP、PDM、EDM、Git各种的用途和区别,硬件型初创公司需要哪些管理工具?

目录 前言&#xff1a; 一、ERP&#xff08;企业资源计划&#xff09; 二、PDM&#xff08;产品数据管理系统&#xff09; 三、EDM&#xff08;文档管理系统&#xff0c;有时也指电子邮件营销&#xff09; 四、Git 总结 五、硬件研发、生产型企业需要哪些管理工具&#…...

通过剪枝与知识蒸馏优化大型语言模型:NVIDIA在Llama 3.1模型上的实践与创新

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…...

DOM型xss靶场实验

xss是什么&#xff1f; XSS是一种经常出现在web应用中的计算机安全漏洞&#xff0c;它允许恶意web用户将代码植入到提供给其它用户使用的页面中。比如这些代码包括HTML代码和客户端脚本。攻击者利用XSS漏洞旁路掉访问控制--例如同源策略(same origin policy)。这种类型的漏洞由…...

华为---端口隔离简介和示例配置

目录 1. 端口隔离概念 2. 端口隔离作用 3. 端口隔离优点 4. 端口隔离缺点 5. 端口隔离的方法和应用场景 6. 端口隔离配置 6.1 端口隔离相关配置命令 6.2 端口隔离配置思路 7. 示例配置 7.1 示例场景 7.2 网络拓扑图 7.3 基本配置 7.4端口隔离配置与验证 7.4.1 双…...

Android 架构模式之 MVC

目录 架构设计的目的对 MVC 的理解Android 中 MVC 的问题试吃个小李子ViewModelController 大家好&#xff01; 作为 Android 程序猿&#xff0c;MVC 应该是我们第一个接触的架构吧&#xff0c;从开始接触 Android 那一刻起&#xff0c;我们就开始接触它&#xff0c;可还记得我…...

节点使用简介:comfyui-photoshop

1、安装comfyui-photoshop 略过 一点要注意的是&#xff1a;在Photoshop上的安装增效工具&#xff0c;要通过Creative Cloud 桌面应用程序进行安装&#xff0c;才能成功在增效工具中显示&#xff0c;直接通过将文件解压到Plug-ins路径行不通&#xff08;至少对我来说行不通&am…...

使用Go语言将PDF文件转换为Base64编码

使用 Go 语言将 Base64 编码转换为 PDF 文件-CSDN博客本文介绍了如何使用 Go 语言将 Base64 编码转换为 PDF 文件&#xff0c;并保存到指定路径。https://blog.csdn.net/qq_45519030/article/details/141225772 在现代编程中&#xff0c;数据转换和编码是常见的需求。本文将介绍…...

XSS Game

关卡网址&#xff1a;XSS Game - Learning XSS Made Simple! | Created by PwnFunction 1.Ma Spaghet! 见源代码分析得&#xff0c;somebody接收参数&#xff0c;输入somebody111查看所在位置 使用input标签 <input onmouseoveralert(1337)> 2.Jefff jeff接收参数,在ev…...

???牛客周赛55:虫洞操纵者

题目描述 \,\,\,\,\,\,\,\,\,\,你需要在一个可以上下左右移动的 nnn\times nnn 棋盘上解开一个迷宫&#xff1a;棋盘四周都是墙&#xff1b;每个方格要么是可以通过的空方格 ′0′\sf 0′0′ &#xff0c;要么是不可通过的墙方格 ′1′\sf 1′1′ &#xff1b;你可以沿着空方格…...

Unity3D开发之OnCollisionXXX触发条件

A和B碰撞触发OnCollision函数条件如下&#xff1a; 1.A和B都要有collider。&#xff08;子物体有也可以&#xff09; 2.A和B至少有一个刚体&#xff08;Rigidbody&#xff09;组件&#xff0c;且刚体的isKinematic为false。如果为true不会触发。 3.挂载脚本的物体必须有刚体…...

spfa()算法(求最短路)

spfa算法是对bellman_ford算法的优化&#xff0c;大部分求最短路问题都可以用spaf算法来求。 注意&#xff1a; &#xff08;1&#xff09;如若图中有负权回路&#xff0c;不能用spfa算法&#xff0c;要用bellman_ford算法&#xff1b;若只有负权边&#xff0c;则可以用 spf…...

聊聊国产数据库的生态系统建设

生态系统是指在自然界中&#xff0c;生物与环境构成统一的整体&#xff0c;之间相互影响相互制约&#xff0c;并在一定时期内处于相对稳定的动态平衡状态。所谓数据库的生态系统&#xff0c;从用户的角度看&#xff0c;就是充分打通产品使用过程中上下游的关联&#xff0c;使其…...

JDK源码解析:LinkedList

1、背景 我们咨询一下腾讯混元大模型&#xff0c;什么是“LinkedList”。 以下是混元大模型的回答&#xff1a; LinkedList 是 Java 集合框架中的一种数据结构&#xff0c;它实现了 List 和 Deque 接口。LinkedList 是一个双向链表&#xff0c;这意味着每个元素都包含对前一个和…...

drawio的问题

drawio的问题 先给出drawio的链接https://app.diagrams.net/ 我在用overleaf写论文的过程中&#xff0c;发现了一个问题&#xff0c;就是使用drawio画好图之后&#xff0c;只能保存以下几个选项&#xff1a; 但是不管是什么类型&#xff0c;在overleaf上面图片都不显示。如果…...

零基础学习Redis(3) -- Redis常用命令

Redis是一个 客户端-服务器 结构的程序&#xff0c;Redis客户端和服务器可以在同一台主机上&#xff0c;也可以在不同主机上&#xff0c;客户端和服务器之间通过网络进行通信。服务器端负责存储和管理数据。客户端则可以通过命名对服务端的数据进行操作。 Redis客户端有多种&a…...

响应式Web设计:纯HTML和CSS的实现技巧-1

响应式Web设计&#xff08;Responsive Web Design, RWD&#xff09;是一种旨在确保网站在不同设备和屏幕尺寸下都能良好运行的网页设计策略。通过纯HTML和CSS实现响应式设计&#xff0c;主要依赖于媒体查询&#xff08;Media Queries&#xff09;、灵活的布局、可伸缩的图片和字…...

FrereRTOS事件组

文章目录 一、事件组概念与操作1、事件组的概念2、事件组的操作 二、事件组函数1、创建2、删除3、设置事件4、等待事件5、同步点 三、示例&#xff1a;广播四、示例&#xff1a;等待一个任意事件五、示例: 等待多个事件都发生 学校组织秋游&#xff0c;组长在等待&#xff1a; …...

【经典算法】BFS_最短路问题

目录 1. 最短路问题介绍2. 算法原理和代码实现(含题目链接)1926.迷宫中离入口最近的出口433.最小基因变化127.单词接龙675.为高尔夫比赛砍树 3. 算法总结 1. 最短路问题介绍 最短路径问题是图论中的一类十分重要的问题。本篇文章只介绍边权为1(或边权相同)的最简单的最短路径问…...

【题目/训练】:双指针

引言 我们已经在这篇博客【算法/学习】双指针-CSDN博客里面讲了双指针、二分等的相关知识。 现在我们来做一些训练吧 经典例题 1. 移动零 思路&#xff1a; 使用 0 当做这个中间点&#xff0c;把不等于 0(注意题目没说不能有负数)的放到中间点的左边&#xff0c;等于 0 的…...

LLVM - 编译器后端-指令选择

一&#xff1a;概述 任何后端的核心都是指令选择。LLVM 实现了几种方法&#xff1b;在本篇文章中&#xff0c;我们将通过选择有向无环图&#xff08;DAG&#xff09;和全局指令选择来实现指令选择。 在本篇文章中&#xff0c;我们将学习以下主题&#xff1a; • 定义调…...

ES+FileBeat+Kibana日志采集搭建体验

1.环境准备 需要linux操作系统&#xff0c;并安装了docker环境 此处使用虚拟机演示。&#xff08;虚拟机和docker看参考我之前写的文章&#xff09; VirtualBox安装Oracle Linux 7.9全流程-CSDN博客 VirtualBox上的Oracle Linux虚拟机安装Docker全流程-CSDN博客 简单演示搭建ES…...

Dockerfile常用指令详解

Dockerfile 是一个用于定义 Docker 镜像构建过程的脚本文件&#xff0c;其中包含了一系列指令&#xff0c;用于指定如何构建和配置镜像。以下是一些常用的 Dockerfile 指令及其示例用法&#xff1a; 1. FROM 指定基础镜像&#xff0c;Dockerfile 必须以该指令开始。 示例&am…...

【vue】浏览器兼容相关

Vue.js 是一个流行的前端 JavaScript 框架&#xff0c;它支持构建单页应用和复杂的用户界面。Vue.js 的核心库本身对浏览器的支持情况如下&#xff1a; Vue.js 2.x 最低支持版本&#xff1a;IE9 及以上版本。特性支持&#xff1a;ES5。兼容性&#xff1a;Vue 2.x 在发布时就考…...

【区块链+金融服务】基于区块链的区域股权金融综合服务平台 | FISCO BCOS应用案例

区域性股权市场是我国资本市场的重要组成部分&#xff0c;是多层次资本市场体系的基石。区块链技术与区域性股权市场 分散特征天然匹配&#xff0c;从新型金融基础设施层面为场外参与各方提供公共的可信服务&#xff0c;以技术手段完善市场基础条 件&#xff0c;弥补区域性短板…...

string字符串和json对象相互转换问题

//响应体String responseStr EntityUtils.toString(response.getEntity());log.debug("下单响应码:{},响应体:{}",statusCode,responseStr);if(statusCode HttpStatus.OK.value()){JSONObject jsonObject JSONObject.parseObject(responseStr);if(jsonObject.cont…...

【生成式人工智能-十一一个不修改模型就能加速语言模型生成的方法】

一个加速语言模型生成的方法 现在语言模型的一个弊端speculative decoding预言家预测的问题 speculative decoding 模块的实现方法NAT Non-autoregressive模型压缩使用搜索引擎 一些更复杂些的speculative decoding 实现方式 speculative decoding 是一个适用于目前生成模型的加…...

Rust 错误处理

Rust 错误处理 Rust 是一种系统编程语言,以其内存安全、高并发和实用性而著称。在 Rust 中,错误处理是一个核心概念,它通过提供 Result 和 Option 类型来鼓励开发者显式地处理可能出现的错误,而不是依赖异常机制。本文将深入探讨 Rust 中的错误处理机制,包括 Result 和 O…...

程序与进程 linux系统

程序与进程 程序 &#xff08; program &#xff09;&#xff1a; 通常为 binary program &#xff0c;放置在储存媒体中&#xff08;如硬盘、光盘、软盘、磁带等&#xff09;&#xff0c; 为实体文件的型态存在&#xff1b;二进制文件&#xff0c;比如静态 /bin/date…...

使用MongoDB构建AI:Story Tools Studio将生成式AI引入Myth Maker AI游戏

Story Tools Studio利用先进的生成式AI技术&#xff0c;打造沉浸式、个性化、无穷尽的情景体验。 Story Tools Studio创始人兼首席执行官Roy Altman表示&#xff1a;“我们的旗舰游戏Myth Maker AI采用的是我们自主研发的、以AI为驱动的专家指导型故事生成器MUSE&#xff0c;它…...

鸿蒙UIAbility组件概述(二)

鸿蒙UIAbility组件概述 UIAbility组件基本用法指定UIAbility的启动页面获取UIAbility的上下文信息 UIAbility组件与UI的数据同步使用EventHub进行数据通信使用AppStorage/LocalStorage进行数据同步 UIAbility组件间交互&#xff08;设备内&#xff09;启动应用内的UIAbility启动…...

Oracle(70)如何优化SQL查询?

优化SQL查询是数据库管理的重要部分&#xff0c;旨在提高查询性能&#xff0c;减少响应时间和资源消耗。以下是一些常见的SQL查询优化技术&#xff0c;结合代码示例详细说明。 1. 使用索引 索引是优化查询性能的最常见方法之一。索引可以显著减少数据检索的时间。 示例 假设…...

深度剖析:Jenkins构建任务无法中断的原因及解决方案

个人名片 &#x1f393;作者简介&#xff1a;java领域优质创作者 &#x1f310;个人主页&#xff1a;码农阿豪 &#x1f4de;工作室&#xff1a;新空间代码工作室&#xff08;提供各种软件服务&#xff09; &#x1f48c;个人邮箱&#xff1a;[2435024119qq.com] &#x1f4f1…...

【YOLO】常用脚本

目录 VOC转YOLO划分训练集、测试集与验证集 VOC转YOLO import os import xml.etree.ElementTree as ETdef convert(size, box):dw 1. / size[0]dh 1. / size[1]x (box[0] box[1]) / 2.0y (box[2] box[3]) / 2.0w box[1] - box[0]h box[3] - box[2]x x * dww w * dwy…...

Springboot IOC DI理解及实现+JUnit的引入+参数配置

一、JavaConfig 我们通常使用 Spring 都会使用 XML 配置&#xff0c;随着功能以及业务逻辑的日益复杂&#xff0c;应用伴随着大量的 XML 配置文件以及复杂的 bean 依赖关系&#xff0c;使用起来很不方便。 在 Spring 3.0 开始&#xff0c;Spring 官方就已经开始推荐使用 Java…...

CeresPCL 最小二乘插值(曲线拟合)

一、简介 在多项式插值时,当数据点个数较多时,插值会导致多项式曲线阶数过高,带来不稳定因素。因此我们可以通过固定幂基函数的最高次数 m(m < n),来对我们要拟合的曲线进行降阶。之前的函数形式就可以变为: 既然是最小二乘问题,那么就仍然可以使用Ceres来进行求解。 …...

【TCP/IP】自定义应用层协议,常见端口号

互联网中&#xff0c;主流的是 TCP/IP 五层协议 5G/4G 上网&#xff0c;是有自己的协议栈&#xff0c;要比 TCP/IP 更复杂&#xff08;能够把 TCP/IP 的一部分内容给包含进去了&#xff09; 应用层 可以代表我们所编写的应用程序&#xff0c;只要应用程序里面用到了网络通信…...

Frida 的下载和安装

首先要安装好 python 环境 安装 frida 和 工具包 pip install frida frida-tools 查看版本&#xff1a; frida --version 16.4.8 然后到 github 上下载对应 server &#xff08; 和frida 的版本一致 16.4.8&#xff09; Releases frida/frida (github.com) 查看手机或…...

后端开发刷题 | 链表内指定区间反转【链表篇】

描述 将一个节点数为 size 链表 m 位置到 n 位置之间的区间反转&#xff0c;要求时间复杂度 O(n)O(n)&#xff0c;空间复杂度 O(1)O(1)。 例如&#xff1a; 给出的链表为 1→2→3→4→5→NULL1→2→3→4→5→NULL, m2,n4 返回 1→4→3→2→5→NULL 数据范围&#xff1a; 链表…...

【NVMe系列-提问页与文章总结页面】

NVMe系列-提问页与文章总结页面 问题汇总NVMe协议是什么&#xff1f;PRP 与 PRP List是做什么的&#xff1f; 已写文章汇总 问题汇总 NVMe协议是什么&#xff1f; PRP 与 PRP List是做什么的&#xff1f; 已写文章汇总...

用生成器函数生成表单各字段

生成器函数生成表单字段是非常合适的用法,避免你要用纯javascript做后台时频繁的制作表单&#xff0c;而不能重复利用 //这里是javascript部分&#xff0c;formfiled.js //生成器函数对字段的处理&#xff0c;让各字段name\className\label\value\placeholder赋值到input的属性…...

【xilinx】O-RAN 无线电接口 - Vivado 2020.1 及更新工具版本的发行说明

描述 记录包含 O-RAN 无线电接口 LogiCORE IP 的发行说明和已知问题&#xff0c;包括以下内容&#xff1a; 一般信息已知和已解决的问题 解决方案 一般信息 可以在以下三个位置找到支持的设备&#xff1a; O-RAN 无线电接口 IP 产品指南&#xff08;需要访问O-RAN 安全站点&…...

结营考试- 算法进阶营地 - DAY11

结营考试 - 算法进阶营地 - DAY11 测评链接&#xff1b; A - 打卡题 考点&#xff1a;枚举&#xff1b; 分析 枚举 a _①_ b _②_ c d&#xff0c;中两个运算符的 3 3 3 种可能性&#xff0c;尝试寻找一种符合要求的答案。 参考代码 #include <bits/stdc.h> usi…...

设计模式: 访问者模式

文章目录 一、介绍二、模式结构三、优缺点1、优点2、缺点 四、应用场景 一、介绍 Visitor 模式&#xff08;访问者模式&#xff09;是一种行为设计模式&#xff0c;它允许在不修改对象结构的前提下&#xff0c;增加作用于一组对象上新的操作。就增加新的操作而言&#xff0c;V…...

selenium底层原理详解

目录 1、selenium版本的演变 1.1、Selenium 1.x&#xff08;Selenium RC时代&#xff09; 1.2、Selenium 2.x&#xff08;WebDriver整合时代&#xff09; 1.3、Selenium 3.x 2、selenium原理说明 3、源码说明 3.1、启动webdriver服务建立连接 3.2、发送操作 1、seleni…...

【Solidity】继承

继承 Solidity 中使用 is 关键字实现继承&#xff1a; contract Father {function getNumber() public pure returns (uint) {return 10;}function getNumber2() public pure virtual returns (uint) {return 20;} }contract Son is Father {}现在 Son 就可以调用 Father 的 …...