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

C++(面向对象编程——继承)

继承基础概念

1.什么是继承?

继承是C++三大特性之一;继承是一个已经存在的类的基础上新建一个类,新建的类拥有已经存在的类的特性。主要提现的是代码复用的思想。新的类继承了基类的所有成员变量成员函数,包括不显示的函数(构造函数,析构函数等)。

2.继承关系

被继承的类叫做基类,继承的类叫做派生类

3.基本语法

class Farther {// 基类成员
};class Son : public Farther{        //private或者protected// 派生类成员
};

 简单的实现,Dog1继承了Dog类的成员函数和成员变量。

#include <iostream>using namespace std;class Dog{
private:string name1 = "狗1";
public:void print(){cout << "我是" << name1 << endl;}
};class Dog1:public Dog{};int main (){Dog d;Dog1 d1;d.print();d1.print();return 0;
}

 

 函数隐藏

函数隐藏是面向对象编程中的一个重要概念,指派生类中定义的同名函数会隐藏基类中的同名函数。比如我Dog中定义的成员函数,我在派生类中可以再写定义一次,但是定义完之后的功能就不再是基类的函数的功能了,相当于新函数会吧旧函数隐藏。这样可以实现派生类和基类差异化。

#include <iostream>using namespace std;class Dog{
private:string name1 = "狗1";
public:void print(){cout << "我是" << name1 << endl;}
};class Dog1:public Dog{
public:void print(){cout << "我是" << "狗2" << endl;}
};int main (){Dog d;Dog1 d1;d.print();d1.print();return 0;
}

构造函数

1.继承中构造函数的限制

C++中规定,派生类无法继承基类的构造函数,派生类的任意一个构造函数都必须直接或间接调用基类的任意一个构造函数

默认情况下,编译器会为每个类增加一个无参构造函数,同时会在派生类的无参构造函数中调用基类的无参构造函数

#include <iostream>using namespace std;class Dog{
private:string name1 = "狗1";
public:Dog(){}            //不写的时候系统默认的构造函数
};class Dog1:public Dog{
public://Dog1():Dog() {}//编译器会自动生成一个默认构造函数//这个默认构造函数会隐式调用基类的默认构造函数//如果基类没有默认构造函数,则必须显式调用基类的某个构造函数
};int main (){Dog d;Dog1 d1;return 0;
}

 上面这种情况不会报错,但是如果这时候你想传参改变成员变量初始值,只改基类的构造函数可以吗?是不可以的,上面说了,构造函数是不继承的,是调用基类的构造函数,也就是我想初始化d1,但是我调用的是Dog(string name1):name1(name1){};构造函数,可我定义的是Dog1的对象,这个时候就会报错。

错误说的是没有与'Dog1(const char [4])'调用匹配的函数,也就是派生类里没有处理参数的构造函数,只有默认的Dog1():Dog(){}。

上面的内容看不懂没关系,因为因为包含了透传构造的内容,可以先简单看一下学完透传再开看。

2.透传构造

上面是基类中编译器默认生成的构造函数,这就是一个透传构造函数,只是没有传参,意思是调用的基类的构造函数Dog()。可以这么理解下面的图:派生类Dog1接收初始化传入的参数name1,在调用基类的构造函数,把name1透传给基类的构造函数实现初始化,派生类调用基类的构造函数实现初始化。

 实现可传参的构造函数:

#include <iostream>using namespace std;class Dog{
private:string name1;
public:Dog(){}Dog(string name1):name1(name1){}string get_name1(){return name1;}void print(){cout << "我是" << name1 << endl;}
};class Dog1:public Dog{
public:Dog1():Dog(){}Dog1(string name1):Dog(name1){}void print(){cout << "我是" << this->get_name1() << endl;}
};int main (){Dog d("狗1");Dog1 d1("狗2");d.print();d1.print();return 0;
}

 3.委托构造函数

和透传类似,我当前派生类把参数委托给自己的构造函数,然后在调用基类的构造函数实现,其实比较多此一举,多一次调用,代码性能就越差,所有不推荐这么写。

#include <iostream>using namespace std;class Dog{
private:string name1;
public:Dog(){}Dog(string name1):name1(name1){}string get_name1(){return name1;}void print(){cout << "我是" << name1 << endl;}
};class Dog1:public Dog{
public:Dog1():Dog1("狗2"){}        //委托下面的构造函数Dog1(string name1):Dog(name1){}        //调用基类构造函数void print(){cout << "我是" << this->get_name1() << endl;}
};int main (){Dog d("狗1");Dog1 d1;d.print();d1.print();return 0;
}

委托构造的时候要避免闭环,比如下面这种情况。

    class Dog1:public Dog{Dog1():Dog1("狗2"){}                    //调用下面的构造函数Dog1(string name1):Dog1(){}                //又去调用第一个构造函数}

4.继承构造

这是C++11的新特性,继承构造不是构造函数能继承,而是表现出类似继承的特性,本质上还是透传构造。

#include <iostream>using namespace std;class Dog{
private:string name1;
public:Dog(){}Dog(string name1):name1(name1){}string get_name1(){return name1;}void print(){cout << "我是" << name1 << endl;}
};class Dog1:public Dog{
public:using Dog::Dog;                        //加上这个语句,编译器会自动添加下面的语句//Dog1():Dog(){}        //委托下面的构造函数//Dog1(string name1):Dog(name1){}        //调用基类构造函数void print(){cout << "我是" << this->get_name1() << endl;}
};int main (){Dog d("狗1");Dog1 d1("狗2");d.print();d1.print();return 0;
}

对象的创建与销毁流程

下面这个代码测试的是不同位置的对象创建和销毁先后顺序和流程。

1.流程:

(1).首先是主函数开始前(编译的时候)先给静态成员变量初始化

(2).主函数开始

(3)定义一个Son类型的变量:

                基类成员变量初始化

                基类构造函数

                派生类成员变量初始化

                派生类构造函数

(4)输出"正在使用s中:调用s的各种功能"。

(5)销毁一个Son类型的变量

                派生类析构函数

                派生类成员变量析构函数

                基类析构函数

                基类成员变量析构函数

(6)程序结束

(7)静态成员变量调用析构函数,越早初始化的最晚被释放

2.规律:

(1)对象创建和销毁流程相反

(2)静态成员变量的生命周期是程序的整个运行周期,在程序结束后才释放。

(3)创建对象的时候,先对基类成员对象初始化再调用基类的构造函数(从最早的基类套娃)

#include <iostream>using namespace std;class Value                                 //作为其他类的变量使用
{
private:string name;public:Value(string name):name(name){cout << name << "构造函数" << endl;}~Value(){cout << name << "析构函数" << endl;}
};class Father
{
public:static Value s_value;                   // 静态成员变量Value value = Value("Father的成员变量");  // 成员变量Father(){cout << "Father的构造函数" << endl;}~Father(){cout << "Father的析构函数" << endl;}
};Value Father::s_value = Value("Father的静态成员变量");class Son:public Father
{
public:static Value s_value;                // 静态成员变量Value value = Value("Son的成员变量");  // 成员变量Son(){cout << "Son的构造函数" << endl;}~Son(){cout << "Son的析构函数" << endl;}
};Value Son::s_value = Value("Son的静态成员变量");int main()
{cout << "主函数开始" << endl;Son* s = new Son;cout << "正在使用s中:调用s的各种功能" << endl;delete s;cout << "主函数结束" << endl;return 0;
}

 

多重继承

1.基本使用:

一个派生类有多个基类,也就是继承多个基类,派生类继承所有的基类的成员变量和成员函数。

#include <iostream>using namespace std;class Name      //定义名字类
{
private:string name = "Lisa";
public:string get_name(){return name;}Name() {cout << "name" << endl;}
};class Age       //定义年龄类
{
private:int age = 5;
public:int get_age(){return age;}Age() {cout << "age" << endl;}
};class Cat : public Name,public Age              //继承年龄和名字类
{
private:string color = "red";
public:Cat(){}                     //默认的透传构造函数
};int main()
{Cat c1;cout << c1.get_age() << endl << c1.get_name() << endl;return 0;
}

2.二义性:

2.1 重名成员

派生类继承的多个基类中存在相同的成员变量或者成员函数,这个时候直接调用编译器不知道你调用的是来自哪个基类的成员,就会出现二义性问题。

解决办法:在重名的成员前加上作用域限定符号——(基类名::)

#include <iostream>using namespace std;class Name      //定义名字类
{
private:string name = "Lisa";
public:string get_name()const{         //不对数据改变可以使用const修饰return name;}Name(){}void print()const{cout << "name:" << name << endl;}
};class Age       //定义年龄类
{
private:int age = 5;
public:int get_age()const{return age;}Age() {}void print()const{cout << "age:" << age << endl;}
};class Cat : public Name,public Age              //继承年龄和名字类
{
private:string color = "red";
public:Cat(){}                     //默认的透传构造函数
};int main()
{Cat c1;c1.Name::print();                 //加上作用域限定符c1.Age::print();return 0;
}

2.2 菱形继承(钻石继承)

一个派生类有多个基类,这多个基类又继承同一个类,如下图类似与菱形(钻石)。

这个时候创建一个Cat类型的对象,我想调用Ainaml中的成员变量或者函数就会报错,因为Name和Age中都继承了Aniaml的成员,Name和Age中都有从Animal继承的成员,编译器就不知道你调用的成员来自于Name还是Age中,会出现二义性问题。

解决方法:
(1)方法一:

加上作用域限定符号,告诉编译器,调用的成员来自哪个基类。

#include <iostream>using namespace std;class Animal
{
private:string breed = "银渐层";       //品种
public:string get_breed(){return breed;}void print(){cout << breed << endl;}
};class Name:public Animal      //定义名字类
{};class Age:public Animal       //定义年龄类
{};class Cat : public Name,public Age              //继承年龄和名字类
{};int main()
{Cat c1;//c1.print();                    //错误c1.Age::print();c1.Name::print();return 0;
}
(2).方法二:

使用虚继承。

当一个类被虚继承的时候,虚拟机会为该基类生成虚机类表,一个类只有一个虚机类表。而虚继承的派生类内部会增加一个隐藏的指针成员(虚基类指针),这样菱形继承的时候派生类就会继承两个不同的虚机指针而不是直接继承成员变量和成员函数,通过这几个指针找到函数,就不存在二义性问题。

虚继承发生在Animal和Name与Age之间,Cat是直接继承Name 和Age类,同时把隐藏的指针继承,这样虚拟机就可以通过两个不同的指针都可以找到的是同一个虚机类表,调用成员函数和成员变量。

#include <iostream>using namespace std;class Animal
{
public:void print(){cout << "虚机类表" << endl;}
};class Name:virtual public Animal      //定义名字类
{};class Age:virtual public Animal       //定义年龄类
{};class Cat : public Name,public Age              //继承年龄和名字类
{};int main()
{Animal a;cout << sizeof(Animal) << endl;cout << sizeof(a) << endl;Name n;cout << sizeof(Name) << endl;cout << sizeof(n) << endl;Cat c1;cout << sizeof(Cat) << endl;cout << sizeof(c1) << endl;c1.print();return 0;
}

继承类型与权限

了解了继承的基础知识后,最后再说三种不同的继承类型和它们的权限区别。

1.公有继承

(1)在类中可以被直接调用修改。

(2)被继承到派生类中,也可以被直接调用修改。

(3)在类外也可以通过对象直接调用查看修改。

2.保护继承

(1)在类中可以被直接调用查看修改。

(2)被继承到派生类中也可以被你直接调用修改。

(3)在类外不可以通过对象直接调用修改,必须借助get或者set成员函数接口调用。

3.私有继承

(1)在类中可以被直接调用查看修改。

(2)被继承到派生类中不可以直接被调用查看修改,必须借助get或者set成员函数接口调用。

(3)在类外也不可以通过对象直接调用修改。

总结:

在类中

在派生类中

在类外

public

可以直接调用

可以直接调用

可以直接调用

protected

可以直接调用

可以直接调用

不可以直接调用

private

可以直接调用

不可以直接调用

不可以直接调用

#include <iostream>using namespace std;class Animal
{
private:string name1 = "金渐层";
protected:string name2 = "银渐层";
public:string name3 = "缅因猫";string get_name1()const{return name1;}string get_name2()const{return name2;}string get_name3()const{return name3;}void print()const{cout << name1 << endl;              //在自己的类中都可以直接调用cout << name2 << endl;cout << name3 << endl;}
};class Cat : public Animal              //继承年龄和名字类
{
public:void print()const{cout << get_name1() << endl;        //派生类私有类不可直接调用cout << name2 << endl;cout << name3 << endl;}
};int main()
{Animal a;a.print();cout << "#######################" << endl;Cat c;c.print();cout << "#######################" << endl;cout << c.get_name1() << endl;              //私有和保护继承类外需要接口调用cout << c.get_name2() << endl;cout << c.name3 << endl;                    //公有继承可以直接调用return 0;
}

函数覆盖

注意:函数也叫函数重写,有的人喜欢叫它函数重写

先了解后面还会讲

概念:

函数覆盖是实现运行时多态的核心,它允许派生类重新定义基类的虚函数,实现特定于派生类的行为,是继承体系中最重要的特性之一。被virtual修饰的成员函数就是虚函数,如果一个类有虚函数,就会给该类生成一个vtable(虚机类表)。

虚函数性质:

  • 虚函数具有传递性,基类的虚函数可以把派生类新覆盖的函数编程虚函数。
  • 成员函数可以设置为虚函数,静态成员函数不能设置为虚函数。
  • 构造函数不能设置为虚函数,析构函数可以设置为虚函数。
  • 如果函数声明与定义分离,只需要使用virtual修饰声明即可。
  • 在C++11中,可以使用override关键字验证是否覆盖成功。
#include <iostream>using namespace std;class Animal
{
public:virtual void eat(){cout << "吃东西" << endl;}
};class Dog:public Animal
{
public:void eat() override // 如果不报错,说明覆盖成功{cout << "吃狗粮" << endl;}// 错误:覆盖失败
//    void eat2() override
//    {
//        cout << "吃肉" << endl;
//    }
};int main()
{Dog d;d.eat();return 0;
}

练习: 

定义学生类,有姓名,学号,性别,年龄等私有成员变量,有构造和析构函数,有打印信息的成员函数。

1.定义大学生类,继承自学生类,大学生有专业名、成绩的私有成员变量,还有是否获得奖学金的成员函数(成绩为判断依据)。隐藏基类打印信息的成员函数,新的打印信息的成员函数也要能打印姓名、学号、性别、年龄信息。

2.要求通过构造函数可以给属性赋予初始值。

3.再定义研究生类,继承自大学生类,有导师姓名和工资的私有成员变量,有打印工资这个成员函数。

4.要求通过构造函数可以给属性赋予初始值,要求通过构造函数可以给属性赋予初始值。 

#include <iostream>using namespace std;class Student
{
private:string name;            //学生姓名string code;            //学生学号char sex;               //学生性别int age;                //学生年龄
public:Student(string name,string code,char sex,int age):name(name),code(code),sex(sex),age(age) {}string get_name()const{return name;}string get_code()const{return code;}char get_sex()const{return sex;}int get_age()const{return age;}void print()const{cout << "名字:" << name << endl;cout << "学号:" << code << endl;cout << "性别:" << sex << endl;cout << "年龄:" << age << endl;}~Student(){cout << "析构函数" << endl;}
};class Ustudent:public Student{
private:string professhion;         //专业double score;               //成绩char scholarship;           //是否有奖学金
public:Ustudent(string name,string code,char sex,int age,string profession,double score,char scholarship):Student(name,code,sex,age){this->professhion = profession;this->score = score;this->scholarship = scholarship;}string get_professhion()const{return professhion;}double get_score()const{return score;}char get_scholarship()const{return scholarship;}void print()const{cout << "名字:" << this->get_name() << endl;cout << "学号:" << this->get_code() << endl;cout << "专业:" << professhion << endl;cout << "性别:" << this->get_sex() << endl;cout << "年龄:" << this->get_age() << endl;cout << "成绩:" << score << endl;cout << "是否有奖学金:" << scholarship << endl;}
};class Graduate:public Ustudent{
private:string teachername;         //导师名字double salar;               //薪水
public:Graduate(string name,string code,char sex,int age,string profession,double score,char scholarship,string teachername,double salar):Ustudent(name,code,sex,age,profession,score,scholarship){this->teachername = teachername;this->salar = salar;}void print()const{cout << "名字:" << this->get_name() << endl;cout << "学号:" << this->get_code() << endl;cout << "专业:" << this->get_professhion() << endl;cout << "性别:" << this->get_sex() << endl;cout << "年龄:" << this->get_age() << endl;cout << "成绩:" << this->get_score() << endl;cout << "是否有奖学金:" << this->get_scholarship() << endl;cout << "导师姓名:" << teachername << endl;cout << "工资:" << salar << endl;}
};int main (){Student s1("张三","202111110132",'f',18);Ustudent s2("王五","202111110133",'f',22,"嵌入式",88.8,'y');Graduate s3("李四","202111110134",'m',23,"软件",98.8,'y',"吃个桃桃好凉凉",400);cout << "########################" << endl << "学生1:" << endl;s1.print();cout << "########################" << endl << "学生2:" << endl;s2.print();cout << "########################" << endl << "学生3:" << endl;s3.print();cout << "########################" << endl;return 0;
}

相关文章:

C++(面向对象编程——继承)

继承基础概念 1.什么是继承&#xff1f; 继承是C三大特性之一&#xff1b;继承是一个已经存在的类的基础上新建一个类&#xff0c;新建的类拥有已经存在的类的特性。主要提现的是代码复用的思想。新的类继承了基类的所有成员变量和成员函数&#xff0c;包括不显示的函数&…...

Unity Shader开发-着色器变体(2)-定义着色器变体

一.定义着色器变体 定义一个着色器变体&#xff08;Shader Variant&#xff09;从概念和实现上讲&#xff0c;主要包括以下几个核心部分 1.使用预编译指令来声明变体关键字 关键字是驱动变体生成的“开关”。它们是简单的字符串标识符&#xff0c;用于在 Shader 代码中标记不…...

Cookie和Session的作用和区别

Cookie 客户端持久化保存服务器数据的一种机制&#xff08;持久化存储就是存硬盘里&#xff09;。Cookie文件数据为键值对形式&#xff0c;客户端根据服务器域名的不同分别存储Cookie&#xff0c;不同域名的Cookie不同&#xff0c;不会产生冲突。 典型应用场景&#xff1a; 保…...

Redis集群部署终极指南:架构选型、生产部署与深度优化

第一部分&#xff1a;Redis集群技术全景解析 1.1 Redis集群演进史 单机时代&#xff08;2009-2012&#xff09;&#xff1a;Redis 2.8之前&#xff0c;纯单机模式复制时代&#xff08;2012-2015&#xff09;&#xff1a;Redis 2.8引入PSYNC改进复制哨兵时代&#xff08;2015-…...

腾讯云IM即时通讯:开启实时通信新时代

一、引言 在当今数字化浪潮席卷全球的时代&#xff0c;即时通讯已然成为互联网世界中不可或缺的关键元素。无论是个人日常生活中的社交互动&#xff0c;还是企业运营里的高效协作&#xff0c;即时通讯都发挥着举足轻重的作用&#xff0c;已然渗透到人们生活与工作的每一个角落…...

基于Qt的UDP主从服务器设计与实现

概述 一个基于Qt框架实现的UDP主从服务器系统&#xff0c;该系统具备自动主机选举、故障转移和状态同步等关键功能&#xff0c;适用于分布式能源管理系统中的设备通信与协调。 系统核心功能 1. 自动主机选举与故障转移 系统通过优先级机制实现自动主机选举&#xff0c;当主机…...

JVM(8)——详解分代收集算法

JVM 的分代收集算法不是一种具体的垃圾收集算法实现&#xff0c;而是一种指导思想和设计原则&#xff0c;是现代 JVM 垃圾收集器的基石。其核心思想源于对程序运行过程中对象生命周期分布的观察&#xff08;即弱分代假说&#xff09;。 核心思想与理论基础&#xff1a;分代假说…...

深入Java面试:从Spring Boot到微服务

深入Java面试&#xff1a;从Spring Boot到微服务 在准备互联网大厂的Java岗位面试时&#xff0c;掌握核心技术栈是关键。本文将从技术栈中选取几个重要的技术点进行探讨&#xff0c;帮助你在面试中脱颖而出。 问题一&#xff1a;Spring Boot的核心特性是什么&#xff1f; 面…...

【软考高级系统架构论文】论无服务器架构及其应用

论文真题 近年来,随着信息技术的迅猛发展和应用需求的快速更迭,传统的多层企业应用系统架构面临越来越多的挑战,已经难以适应这种变化。在这一背景下,无服务器架构(Serverless Architecture) 逐渐流行,它强调业务逻辑由事件触发,具有短暂的生命周期,运行于无状态的轻量…...

Snapchat矩阵运营新策略:亚矩阵云手机打造高效社交网络

1. Snapchat平台特性与风控挑战​​ Snapchat作为全球领先的即时社交平台&#xff0c;其独特的阅后即焚功能和强社交属性使其风控系统极为严格&#xff1a; ​​核心风控机制​​ ​​设备指纹检测​​&#xff1a;记录设备ID、系统版本、IP地址等硬件信息​​行为模式分析​…...

BGP路由反射器(RR)实验详解,结尾有详细脚本

目录 路由反射器基础概念 实验拓扑与设计 实验配置步骤 配置验证与排错 实验总结 完整配置命令集 路由反射器基础概念 在传统的IBGP网络中&#xff0c;为了防止路由环路&#xff0c;BGP规定通过IBGP学到的路由不能再传递给其他IBGP对等体&#xff0c;这导致所有IBGP路由…...

【JAVA】数组的使用

文章目录 前言一、数组的基本概念1.1 数组的创建和初始化1.2 数组的基本使用 二、数组是引用类型2.1 初始JVM的内存分布JVM内存划分&#xff08;按功能分区&#xff09; 2.2 基本类型变量与引用类型变量的区别2.3 再谈引用变量2.4 认识null 三、数组作为函数的参数和返回值四、…...

Python的6万张图像数据集CIFAR-10和CIFAR-100说明

CIFAR-10和CIFAR-100数据集是8000万张微小图像数据集的标记子集。CIFAR-10和CIFAR-100都是由AlexKrizhevsky、VinodNair和GeoffreyHinton创建。数据集说明的网页&#xff1a;https://www.cs.toronto.edu/~kriz/cifar.html 一、CIFAR-10数据集 &#xff08;一&#xff09;CIFA…...

CTF--PhP Web解题(走入CTF)

前情提要 分享有趣CTF题目&#xff0c;记录学习过程 题目&#xff08;带注释,方便理解&#xff09; <?php // 开启PHP源代码高亮显示&#xff0c;输出当前文件内容&#xff08;用于调试/展示&#xff09; highlight_file(__FILE__);// 关闭所有错误报告&#xff0c;防止敏感…...

【Linux仓库】进程概念与基本操作【进程·贰】

&#x1f31f; 各位看官好&#xff0c;我是&#xff01; &#x1f30d; Linux Linux is not Unix &#xff01; &#x1f680; 今天来学习Linux中进程概念与基本操作。 &#x1f44d; 如果觉得这篇文章有帮助&#xff0c;欢迎您一键三连&#xff0c;分享给更多人哦&#xff01…...

Z-Ant开源程序是简化了微处理器上神经网络的部署和优化

​一、软件介绍 文末提供程序和源码下载 Z-Ant &#xff08;Zig-Ant&#xff09; 是一个全面的开源神经网络框架&#xff0c;专门用于在微控制器和边缘设备上部署优化的 AI 模型。Z-Ant 使用 Zig 构建&#xff0c;为资源受限的硬件上的模型优化、代码生成和实时推理提供端到端…...

面试题-在ts中类型转换的方法

在 TypeScript 中&#xff0c;类型转换主要分为 类型断言&#xff08;Type Assertion&#xff09;、类型守卫&#xff08;Type Guard&#xff09; 和 类型兼容转换 三种方式。以下是详细分类和示例&#xff1a; 一、类型断言&#xff08;Type Assertion&#xff09; 强制编译…...

【论文笔记】【强化微调】T-GRPO:对视频数据进行强化微调

tulerfeng/Video-R1: Video-R1: Reinforcing Video Reasoning in MLLMs [&#x1f525;the first paper to explore R1 for video] 1. 引述 在强化微调中&#xff0c;像 GRPO、DAPO 这样的方法都是对文本或者图片进行微调思考&#xff0c;所以这类微调方法不对时序信息做处理&…...

`shallowReactive` 与 `shallowRef`:浅层响应式 API

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》、《前端求职突破计划》 &#x1f35a; 蓝桥云课签约作者、…...

使用Node.js开发服务端接口

Node.js是一个基于JavaScript的运行时环境&#xff0c;非常适合开发高性能的服务端接口。以下是开发服务端接口的主要方法和步骤。 选择合适的框架 Express、Koa或Fastify是Node.js中常用的框架。Express是最流行的选择&#xff0c;适合快速开发。Koa更轻量&#xff0c;适合需…...

`teleport` 传送 API 的使用:在 Vue 3 中的最佳实践

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》、《前端求职突破计划》 &#x1f35a; 蓝桥云课签约作者、…...

Linux 多种方式实现行转列

目录 一. 前提二. xargs 实现行转列三. paste 实现行转列四. sed 实现行转列 一. 前提 ⏹之前在这下面篇文章中使用sed命令实现了行专列&#xff0c;本篇文章再介绍几种更加简单的方式。 Linux sed案例 &#x1f449; 20231126-2.log 110120 SPLREQUEST 内容1 AAA memberID1…...

AI与SEO关键词协同进化

内容概要 人工智能&#xff08;AI&#xff09;与搜索引擎优化&#xff08;SEO&#xff09;的结合&#xff0c;正深刻变革着关键词策略的制定与执行方式。本文旨在探讨AI技术如何驱动SEO关键词领域的智能化进化&#xff0c;核心在于利用AI强大的数据处理与模式识别能力&#xf…...

C# 网络编程-关于HTTP/HTTPS的基础(一)

一、HTTP基础概念 1. 请求-响应模型 HTTP是基于客户端-服务器的无状态协议&#xff0c;流程如下&#xff1a; 客户端&#xff08;如浏览器&#xff09;发起请求。服务器接收请求并处理。服务器返回响应&#xff0c;包含状态码、Header和响应体。连接关闭&#xff0c;后续请求…...

题解:P11501 [ROIR 2019] 探险队(Day 2)

前言&#xff1a;这道题 dp 做法找环的部分还没有用拓扑做的&#xff0c;补充一下。 这道题其实很像“上司的舞会”&#xff0c;就是求树上最大独立集。 这里我们把每个人向他讨厌的那个人连边&#xff08;发现所有点出度均为 1 1 1&#xff0c;所以这是一个基环树&#xff0…...

读者写者问题与读写锁自旋锁

一、读者写者问题 读者写者问题具有以下特点&#xff1a; 一个交易场所---写者写入数据&#xff0c;读者读数据两种角色---读者&#xff0c;写者三种关系 读者和读者---并发写者和写者---互斥读者和写者---互斥 && 同步 二、读者写者VS生产消费 生产者消费者模型中…...

Sublime text启用vim

打开&#xff1a;首选项 > 设置&#xff0c;在打开的输入框中把 "ignored_packages": ["Vintage"] 修改为 "ignored_packages": []&#xff0c;不忽略Vintage&#xff0c;即为启用Vintage&#xff0c;它是Sublime的内置vim插件。 然后再添加&…...

蚂蚁百宝箱快速创建智能体AI小程序

蚂蚁百宝箱官网https://tbox.alipay.com/community?operationSource1006/ 以下是一篇关于蚂蚁百宝箱快速创建智能体 AI 小程序的图文并茂的博客&#xff1a; 标题&#xff1a;蚂蚁百宝箱快速创建智能体 AI 小程序&#xff0c;开启智能应用新体验 引言 在数字化飞速发展的当…...

【Anconda安装教程】安装到环境配置全流程

目录 前言 一、进入官网下载 二、下载Anconda​编辑 三、安装Anconda 四、配置环境变量 五、验证是否安装成功 六、anaconda的使用 情况一&#xff1a;电脑现在没有装python或者现在装的可以卸载掉 情况二&#xff1a;电脑目前装了python&#xff0c;但想保留它 6.1 进…...

Linux系统编程 | IPC对象---信号量

在前面两篇博客文章中&#xff0c;对Linux系统编程部分IPC三大对象中的消息队列和共享内存的知识体系做了一个大致的梳理&#xff0c;在本篇文章中&#xff0c;将对三大IPC对象中的最后一个信号量做一个总结。如果有需要的博客朋友&#xff0c;可以参考我的Linux系统编程专栏参…...

当数据自己会说话:聚类与分类算法全景解析

从金融风控到医疗诊断&#xff0c;两种机器学习技术如何重塑决策逻辑 在人工智能与数据驱动的时代&#xff0c;聚类和分类作为机器学习的两大核心技术&#xff0c;已成为从海量数据中提取价值的必备工具。它们看似相似——都是将数据划分到不同的组中——但内在逻辑和应用场景却…...

哈佛结构(Harvard Architecture)与冯·诺依曼架构(Von Neumann Architecture)

一、基础概念与历史溯源 哈佛结构 起源&#xff1a;1940年代由哈佛大学开发的Mark I计算机首次采用&#xff0c;专为弹道计算优化。核心特征&#xff1a; 物理分离的存储器&#xff1a;程序指令存储在ROM/Flash&#xff0c;数据存储在RAM&#xff0c;两者独立编址。独立总线系统…...

Python内存使用分析工具深度解析与实践指南(下篇)

文章目录 引言6. guppy3 / Heapy功能安装程序示例适用场景注意事项 7. objgraph功能安装程序示例适用场景注意事项 8. memory_profiler功能安装程序示例适用场景注意事项 9. profile&#xff08;标准库&#xff09;功能程序示例适用场景注意事项 总结对比表 引言 在Python编程…...

经典控制理论:线性化笔记

一、弹簧阻尼系统 求B点的位置X0&#xff0c;与弹簧形变后的位置X1的关系 ---- 解&#xff1a; 二、直流电动机模型 求输出转速与输入电压的关系 解&#xff1a;...

【StarRocks系列】查询优化

步骤参考官网 分析查询 | StarRocks StarRocks-Profile分析及优化指南 StarRocks-Profile分析及优化指南 - 经验教程 - StarRocks中文社区论坛...

【STM32】STM32的中断系统寄存器NVIC、EXTI

文章目录 中断概述中断的概念为什么需要中断STM32的中断 STM32的中断体系架构NVICNVIC的介绍中断优先级优先级寄存器优先级组 EXTI 中断概述 中断的概念 在主程序运行过程中&#xff0c;出现了特定事件&#xff0c;使得CPU暂停当前正在运行的程序&#xff0c;转而去处理这个事…...

LLM-201: OpenHands与LLM交互链路分析

一、核心交互链路架构 #mermaid-svg-ZBqCSQk1PPDkIXNx {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-ZBqCSQk1PPDkIXNx .error-icon{fill:#552222;}#mermaid-svg-ZBqCSQk1PPDkIXNx .error-text{fill:#552222;strok…...

税务 VR 虚拟体验,带来全新办税感受

在过去&#xff0c;企业办税难题诸多。申报纳税高峰期&#xff0c;办税服务厅人满为患&#xff0c;财务人员需早起取号排队&#xff0c;耗费大量时间。传统办税流程复杂&#xff0c;涉及多环节和部门&#xff0c;资料繁多&#xff0c;若准备不全或有误就得重新准备&#xff0c;…...

【Linux 驱动中断】

Linux 驱动中断 一、GIC 控制器&#xff1a;硬件中断的枢纽二、GPIO 中断&#xff1a;设备交互的常见入口三、Tasklet 与软中断&#xff1a;高效的异步处理机制3.1 Tasklet3.2 软中断 四、工作队列&#xff1a;灵活的任务处理框架4.1 共享工作队列4.2 自定义工作队列4.3 延迟工…...

ali 轻量服务器安装nginx

# Ubuntu sudo apt install nginx-light # 精简版 # CentOS sudo yum install nginx #启动并设置开机自启 sudo systemctl daemon-reload sudo systemctl start nginx sudo systemctl enable nginx #验证安装 nginx -v curl -I 127.0.0.1 #常用命令&#xff1a; # 重新加载配…...

2025年- H83-Lc191--139.单词拆分(动态规划)--Java版

1.题目描述 2.思路 字符串s是一个容器&#xff08;一个背包&#xff09;&#xff0c;wordDict词典是物品&#xff0c;这里面的每个物品我们可以使用多次。 动归五部曲 &#xff08;1&#xff09;字符串的长度为i&#xff0c;dp[i]true。 dp[s.size] dp[0]代表空字符串 &#x…...

【好用但慎用】Windows 系统中将所有 WSL 发行版从 C 盘迁移到 非系统 盘的完整笔记(附 异常处理)

&#x1f680; 将所有 WSL 发行版从 C 盘迁移到 I 盘的完整教程&#xff08;含 Podman / NVIDIA Workbench / Ubuntu 等&#xff09; 【无标题】使用 Chocolatey 安装 WSL 管理工具 LxRunOffline-CSDN博客 免责声明 重要提示 在执行 WSL 迁移操作前&#xff0c;请务必仔细阅读…...

贪心算法思路详解

文章目录 一、贪心算法是什么&#xff1f;二、贪心算法原理三、再谈背包问题四、活动选择问题五、拟阵理论总结 一、贪心算法是什么&#xff1f; 贪心算法与动态规划算法一样是用于求解最优化类问题的算法&#xff0c;其本质上是基于动态规划算法的改进算法&#xff0c;其所求…...

Keil 安装 CMSIS-FreeRTOS 失败解决方案

一、问题现象 在 Keil 中安装 CMSIS-FreeRTOS 时出现以下错误&#xff1a; &#xff08;1&#xff09; 通过内置工具安装&#xff1a; &#xff08;2&#xff09;通过官网安装&#xff1a; 二、核心原因 Keil 版本过低&#xff0c;与 CMSIS-FreeRTOS 包不兼容&#xff1a; …...

Python打卡DAY33

DAY33&#xff1a;MLP神经网络的训练 恩师浙大疏锦行 知识点&#xff1a; PyTorch和cuda的安装查看显卡信息的命令行命令&#xff08;cmd中使用&#xff09;cuda的检查简单神经网络的流程 数据预处理&#xff08;归一化、转换成张量&#xff09;模型的定义 继承nn.Module类定义…...

RJ45 网口实现千兆传输速率(1Gbps)的原理,涉及物理层传输技术、线缆标准、信号调制及网络协议等多方面的协同设计。以下从技术维度展开详细解析:

一、千兆以太网的标准与物理层基础 1. 标准规范 千兆以太网遵循 IEEE 802.3ab&#xff08;针对双绞线&#xff09;和 IEEE 802.3z&#xff08;针对光纤&#xff09;标准&#xff0c;其中 RJ45 接口对应双绞线场景&#xff0c;核心是通过四对双绞线&#xff08;CAT5e/CAT6 线缆…...

leetcode hot 100之:二叉树的层序遍历

层序遍历和前中后序遍历不一样&#xff0c;大家可以想象的是&#xff1a;前中后序遍历可以用递归&#xff0c;因为他是以子树为标准来选择的&#xff1b;那层序怎么办呢&#xff1f;怎么才能一层层地遍历呢&#xff1f; void First(TreeNode* root) {printf("%d",ro…...

深入解析BERT:语言分类任务的革命性引擎

“BERT的出现&#xff0c;如同在自然语言处理领域投下了一颗认知炸弹——它让机器真正学会了’联系上下文’。” ——自然语言处理研究者普遍共识 在自然语言处理&#xff08;NLP&#xff09;领域&#xff0c;2018年诞生的BERT&#xff08;Bidirectional Encoder Representatio…...

Pycharm中Jupyter Notebook 插件常用快捷键

bg&#xff1a;Jupyter跟LINQPad很像&#xff0c;都是方便写的时候看数据用 快捷键功能Shift Enter执行当前单元格&#xff0c;并跳转到下一个单元格Ctrl Enter执行当前单元格&#xff0c;不跳转&#xff08;留在当前单元格&#xff09;Alt Enter执行当前单元格&#xff0c…...

【Python】Excel表格操作:ISBN转条形码

一、效果 原始文件&#xff1a; 输出文件&#xff1a; 二、代码 import os import logging from openpyxl import load_workbook from openpyxl.drawing.image import Image as ExcelImage from barcode import EAN13 from barcode.writer import ImageWriterlogging.basicCo…...