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

【语法】C++的继承

目录

继承基本语法:

protected访问限定符:

子类和父类之间的赋值兼容规则:

重定义(隐藏): 

继承中的友元/继承中的静态成员: 

子类中的默认成员函数

构造函数/拷贝构造函数:

赋值重载函数:

析构函数: 

 菱形继承问题:

多继承:

解决:

原理:

继承和组合:


面向对象的三大特性分别是封装,继承和多态

而本篇的主要目标就是继承

如果要设计一个学生管理系统,肯定需要定义很多类,例如学生,老师等等

class student
{
public:string _name;int _age;int _score;int _num;
};class teacher
{
public:string _name;int _age;int _id;
}

可以看到student和teacher两个类中都有_name和_age字段,这不就重复了吗,这时就需要用到继承了

在继承中,有父类和子类(或叫基类和派生类)两个概念,我们可以先创建一个父类,用来存student和teacher类中都会用到的字段,再让子类(即student和teacher)去继承父类,就不需要像之前那样每个类都要定义一遍了

class Person
{
public:string _name;int _age;
};class student: public Person
{
public:int _score;int _num;
};class teacher: public Person
{
public:int _id;
}

如上述代码所示,student和teacher都以public的方式继承了Person类,那现在student和teacher里也都有_name和_age变量了。可以看出,继承的目的就是类之间的复用

那为什么前面还要加个public呢?

继承基本语法:

 这是继承的基本格式,也就是说,public是继承方式,那么除了public,就还有private和protected

这就是三种继承方式所对应的区别

也就是说,父类的成员的访问限定符是min(成员在基类的访问限定符,继承方式) (public > protected > private)

需要注意的是,class默认的继承方式是private,struct默认的继承方式是public

class Person
{
protected:string _name = "野兽先辈";int _age;
};class teacher:/*private*/ Person
{
public:teacher(){cout << _name << endl;}private:int _id;
};struct student: /*public*/ Person
{
public:student(){cout << _name << endl;}private:int _id;
};

上述代码中,teacher类是class定义,所以即使继承中不加继承方式,默认就是以private作为继承方式,而student类是struct定义,所以即使继承中不加继承方式,默认就是以public作为继承方式 

不过最好把继承方式写出来

protected访问限定符:

但无论是什么继承方式,父类的private成员在子类中都不可见

难道父类的成员就只能都设为public了吗?虽说设成public的确可以被子类访问,但这样的话不仅子类,类外都可以随意访问。

这时就要用到protected(保护)限定符了

在类中private和protected没有区别,但在继承的子类中有区别:

父类成员设为protected之后,仍可以确保private中在类外不能访问的特性,除此之外,还可以被继承的子类所访问到

因此,protected是专门因继承而出现的访问限定符

class Person
{
protected:string _name = "野兽先辈";int _age;
};class teacher: public Person
{
public:void print(){cout << _name << endl;}private:int _id;
};

这样就没有问题了

在实际运用中一般都是使用public继承,几乎很少用private/protected继承,也不提倡

子类和父类之间的赋值兼容规则:

在正常操作中,类之间的赋值都必须是相同类型,不同类型之间是不能赋值的

class Person
{
protected:string _name;int _age;
};class teacher
{
private:string _title;
};int main()
{teacher s1,s2;Person p1,p2;p1 = p2;//正确p1 = s1;//错误return 0;
}

在Person和teacher没有继承关系时,是不能将teacher的对象赋给Person的对象的

但如果teacher继承了Person呢?

class Person
{
protected:string _name;int _age;
};class teacher : public Person
{
private:string _title;
};int main()
{teacher s1,s2;Person p1,p2;p1 = p2;//正确p1 = s1;//正确return 0;
}   

此时,s1就可以赋给p1了

这就是子类和父类之间的赋值兼容规则

子类对象 可以赋值给 父类的对象 / 父类的指针 / 父类的引用。这里有个形象的说法叫切片
或者切割
。寓意把子类中父类那部分切来赋值过去。这是语法中原生支持的

但反过来不行,即父类对象不能赋值给子类对象

如果这样可以的话,子类中多出来的成员要赋值成什么? 

有一种例外,前面说过,子类对象 可以赋值给 父类指针/引用

那指向子类对象的父类指针,就可以强转成子类指针后赋值给子类指针

teacher t;    
Person* pp = &t;//父类指针指向子类对象,那pp就只能访问到父类成员的那部分
teacher *pt = (teacher*)pp;//这样指向子类对象的父类指针就可以赋值给子类指针了,不过需要强转

引用也是一样

teacher t;    
Person& pp = t;//父类引用指向子类对象,那pp就只能访问到父类成员的那部分
teacher& pt1 = (teacher&)pp;//这样指向子类对象的父类引用就可以赋值给子类(引用)了,不过需要强转
teacher pt2 = (teacher&)pp;

重定义(隐藏): 

在继承体系中父类和子类不在一个作用域,他们都有独立的作用域

class Person
{
public:string _name;int _age = 114;
};class teacher : public Person
{
public:int _age = 514;string _title;
};

上述代码中,可以看到子类和父类都有个_age成员,那此时如果调用teacher实例化对象的_age会调用哪个呢?

答案是teacher中的_age

子类和父类中有同名成员,子类成员将屏蔽父类对同名成员的直接访问,这种情况叫隐藏,
也叫重定义。 

 那如果就是要访问父类的同名成员要怎么办?

class Person
{
public:string _name;int _age = 114;
};class teacher : public Person
{
public:int _age = 514;string _title;void print(){cout << Person::_age << endl;//父类::父类成员}
};

如上述代码所示,只需要指定作用域就好了    父类::父类成员

成员函数只需要函数名相同就构成隐藏,所以如果父类和子类都有一个同名函数,且那个函数的返回值,参数不一样,千万不想错想成是重载!(重载的要求是必须在同一作用域)

继承中的友元/继承中的静态成员: 

 若父类中有友元函数,那继承的子类中不会将友元继承下来(了解即可)

若父类中有static成员,那整个继承体系中无论有多少个子类继承了父类,也都只会有一个唯一的static成员(了解即可)

子类中的默认成员函数

构造函数/拷贝构造函数:

子类的构造函数中会必须先调用父类的构造函数完成父类成员的初始化,再来完成子类成员的初始化

class Person
{
public:Person() { cout << "Person" << endl; }
};class Student : public Person
{
public:Student() :Person(){ cout << "Student" << endl; }
};int main()
{Student s;return 0;
}

输出结果:

那我如果就要在子类的构造函数中初始化父类成员呢?

class Person
{
public:Person() { cout << "Person" << endl; }
protected:string _name;
};class Student : public Person
{
public:Student() :_name("野兽先辈"){ cout << "Student" << endl; }
};int main()
{Student s;return 0;
}

上面代码中我试图用Student的构造函数初始化Person中的_name,但是运行不了

也就是说,要想初始化父类成员,就必须调用父类的构造函数来完成初始化

但好像这样又可以了?

不是不能在子类中给父类成员初始化吗?

确实不能,但上图中的_name = "野兽先辈"并不是初始化(initialization),而是赋值(assignment)

并且其实上图中在赋值之前也已经给_name初始化过了,只不过是隐式调用的Person的构造函数

 也就是说,即使你不写,编译器也会自动调用

对于拷贝构造而言,如果子类没有写拷贝构造函数,那么会自动调用父类的拷贝构造函数对父类成员进行初始化。但如果子类有拷贝构造函数了,那就不会调用父类的拷贝构造函数,而是调用父类的构造函数进行初始化

#include <iostream>struct base 
{base() { std::cout << "base default \n"; };base(const base&) { std::cout << "base copy \n"; }
};struct derived : base
{derived() { std::cout << "derived default \n"; };derived(const derived&) { std::cout << "derived copy \n"; }//有用户定义的拷贝构造,就只会调用父类的构造函数
};int main()
{derived a;std::cout << "\n";derived b(a);
}

输出:

#include <iostream>struct base 
{base() { std::cout << "base default \n"; };base(const base&) { std::cout << "base copy \n"; }
};struct derived : base
{derived() { std::cout << "derived default \n"; };//没有用户定义的拷贝构造,就会调用父类的拷贝构造函数//derived(const derived&) { std::cout << "derived copy \n"; }
};int main()
{derived a;std::cout << "\n";derived b(a);
}

赋值重载函数:

和上面一样,子类的operator=必须要调用父类的operator=完成基类的复制,而且必须显式调用(子类不会隐式调用父类operator=),如下所示

class Person
{
public:Person() { cout << "Person" << endl; }Person& operator=(const Person& p){if (this != &p)_name = p._name;return *this;}
protected:string _name;
};class Student : public Person
{
public:Student() { _name = "野兽先辈";cout << "Student" << endl; }Student& operator=(const Student& s){if (this != &s){Person::operator=(s);_age = s._age;}return *this;}
private:int _age;
};int main()
{Student s1,s2;s1 = s2;return 0;
}

但有些人可能发现,直接在子类的operator=中给父类成员赋值好像也没问题,这是为什么?

需要注意的是,这里并不是隐式调用了Person的operator=,因为子类不会隐式调用父类operator=

这里看起来没问题是因为我们的Person的operator=只完成了最简单的赋值操作,没有复杂操作(例如开辟空间),下面代码就不行了

class Person
{
public:Person(const char* name = ""): _name(new char[strlen(name) + 1]){strcpy(_name, name);cout << "Person constructed: " << _name << endl;}Person(const Person& p): _name(new char[strlen(p._name) + 1]){strcpy(_name, p._name);cout << "Person copy-constructed: " << _name << endl;}Person& operator=(const Person& p){if (this != &p){delete[] _name; // 释放旧资源_name = new char[strlen(p._name) + 1];strcpy(_name, p._name);cout << "Person assigned: " << _name << endl;}return *this;}virtual ~Person(){cout << "Person destructed: " << _name << endl;delete[] _name;}protected:char* _name;
};class Student : public Person
{
public:Student(const char* name = "", int age = 0): Person(name), _age(age){cout << "Student constructed: " << _name << ", Age: " << _age << endl;}Student(const Student& s): Person(s), _age(s._age){cout << "Student copy-constructed: " << _name << ", Age: " << _age << endl;}Student& operator=(const Student& s){if (this != &s){// 如果不调用基类的 operator=,基类的资源不会被正确处理_name = s._name; // 显式调用基类的赋值运算符_age = s._age;cout << "Student assigned: " << _name << ", Age: " << _age << endl;}return *this;}~Student(){cout << "Student destructed: " << _name << ", Age: " << _age << endl;}private:int _age;
};int main()
{Student s1("John", 20);Student s2("Doe", 25);cout << "Assigning s2 to s1..." << endl;s1 = s2; // 调用赋值运算符return 0;
}

如果运行的话,会报错

析构函数: 

如果像上面一样,那应该是要在子类的析构函数里面调用父类的析构函数

struct base {base() { std::cout << "base default \n"; }~base(){ std::cout << "~base \n";}
};struct derived : base{derived() { std::cout << "derived default \n"; }~derived(){ ~base();std::cout << "~derived \n";}
};

但这样却运行不了

 报错为找不到这个函数

实际上我们根本不需要这么做,因为在派生类的析构函数会在被调用完成后自动调用基类的析构函数清理基类成员。因为这样才能保证派生类对象先清理派生类成员再清理基类成员的顺序。

在实际编程几乎很少会在子类析构函数中显示调用父类析构函数(可以这样来结束你使用placement new创建的对象的生命周期),那我如果非要调用,有什么方法吗?

先说一下为什么这里会报错

这里的报错和是不是继承没有关系,因为下面代码也会报同样的错误

class base
{~base(){cout << "~base \n";}void func(){~base();}
};

这段代码的执行顺序其实是先base(),再~

base()会先构造一个base的临时对象。这里其实不难理解,就例如int(),会调用int的默认构造函数创建临时的int变量,它的值是0

int main()
{cout << int() <<endl;return 0;
}

输出:0

所以base()也一样,会调用base的默认构造函数来构建一个临时的base对象

然后会试图调用base对象的operator~重载,如下图

#include <iostream>
using namespace std;
class base
{
public:base(){cout << "constructor base \n";}~base(){cout << "destructor base \n";}void operator~(){cout << "operator ~ \n";}
};class derived : public base
{
public:derived(){cout << "constructor derived \n";}~derived(){base::~base();cout << "destructor derived \n";}
};
int main()
{~base();cout <<"\n";base().operator~();//第一行就相当于这么调用return 0;
}

输出结果:

如上图,第一个和第一行和第三行的代码输出结果相同

所以报错的原因就是base类没有operator~重载

流程:先构造一个临时的base对象,再调用临时base对象的operator~运算符,最后析构这个临时的base对象

所以我们需要明确一点

base::~base();

在前面加上作用域限定符就好了,这样编译器就不会误认为是~运算符了

 菱形继承问题:

多继承:

上面所讲到的继承都叫单继承,并且实际中也一般只会用单继承

#include <iostream>using namespace std;
class base1
{
public:int a = 1;
};class base2 : public base1
{
public:int b = 2;
};class derived : public base2
{
public:int c = 3;
};
int main()
{derived d;return 0;
}

上面代码中,就是一个单继承

derived有base2的成员,base2中有base1的成员

而多继承是子类会同时继承多个父类

#include <iostream>using namespace std;
class base1
{
public:int a = 1;
};class base2
{
public:int b = 2;
};class derived : public base1, public base2
{
public:int c = 3;
};

上图代码,就是一个多继承

derived既有base1的元素,又有base2的元素,并且base1和base2没有联系 

多继承可以说是C++的一个万恶之源了,多继承本身没什么问题,但正是因为有多继承,才会有菱形继承问题

#include <iostream>using namespace std;class base0
{
public:int x = 0;
};
class base1 : public base0
{
public:int a = 1;
};class base2 : public base0
{
public:int b = 2;
};class derived : public base1, public base2
{
public:int c = 3;
};
int main()
{derived d;return 0;
}

这就是一个典型的菱形继承 

当然,也并非必须这样才算菱形继承

 这也是菱形继承

菱形继承会导致什么问题呢?

#include <iostream>using namespace std;class base0
{
public:int x = 0;
};
class base1 : public base0
{
public:int a = 1;
};class base2 : public base0
{
public:int b = 2;
};class derived : public base1, public base2
{
public:int c = 3;void test(){a = 10;b = 20;c = 30;x = 40;}
};

一眼望过去好像没什么问题,但它其实会报错

x是base0的成员,而base1和base2中也有x(继承了base0),而又因为derived继承了base1和base2,所以derived中有两个x,分别是base1和base2的x,如果像上图那样直接调用的话,编译器不知道你要调用哪个x,就会报错

所以需要在前面加上作用域限定符,如下所示

base1::x = 40;
base2::x = 50;

这样会让继承具有数据冗余(被定义多次)和二义性(意义不明确)

解决:

在base1和base2继承base0时加上virtual就可以了

class base0
{
public:int x = 0;
};
class base1 : virtual public base0
{
public:int a = 1;
};class base2 : virtual public base0
{
public:int b = 2;
};class derived : public base1, public base2
{
public:int c = 3;void test(){a = 10;b = 20;c = 30;x = 40;}
};

为什么加上virtual就行了呢?

在继承的前面加上virtual是虚继承的意思,简单来说就是x原来会存两个,但现在x只会存1个了。

原理:

class base0
{
public:int x;
};
class base1 : virtual public base0
{
public:int a;
};class base2 : virtual public base0
{
public:int b;
};class derived : public base1, public base2
{
public:int c;
};int main()
{derived d;d.a = 1;d.b = 2;d.c = 3;d.x = 4;return 0;
}

以上面代码为例,我们来调用调试看看d在内存中的分布

从上面不难看出,a,b,c,x 4个变量都在这里面,但是怎么还有两个看不出来是什么的值呢?

先来给这块内存分个区

可以看到现在x被直接放在子类中,而那两个虚继承了base0的类中,都多出了一个值

这其实是两个指针,叫做虚基表指针(虚拟-基类),而虚基表指针里存的是什么呢?

虚基表指针中存的是虚基表

分别找到这两个虚基表指针存的虚基表后,可以发现,每个虚基表中有8个字节,第一个虚基表存的是14,第二个虚基表中存的是0c,他们都是16进制,转换成10进制后是20和12,这两个值其实是他们各自所属的类(base1和base2)距离虚基类(x(base0))的偏移量

拿上面的图举例,x是在00D2F844的位置,base1是在00D2F830的位置,00D2F830+14 = 00D2F844,正好是x的地址;base2是在00D2F838的位置,00D2F838+0c = 00D2F844,正好是x的地址

问:为什么虚基表是8个字节?这不是只存了一个值吗?

答:上面的例子中只有一个虚基类,所以虚基表中只有一个值,如果子类中有多个虚基类,那虚基表中就会存多个值

继承和组合:

什么是组合?

class B
{class A;//A包含在B类中,是B的成员
}

这就是组合

可以发现继承和组合都可以完成类的复用,那到底是继承好还是组合好?

先说结论:组合更好

为什么?
继承是一种白箱复用,父类对于子类都是透明的,不管父类成员是public还是protected,在子类都可见,一定程度上破坏了父类的封装

组合是一种黑箱复用,父类对于子类不是透明的,父类public的成员,在子类依旧可见,但父类private/protected的成员,在子类就不可见了

因此组合的耦合度较低,而继承的耦合较高,所以组合更好

但并不是继承就没有用武之地:

构成is-a关系的用继承

构成has-a关系的用组合

class car
{
public:...
protected:...}class BWM : public car//宝马是车(is-a的关系用继承)
{
public:...
protected:...
}

上述代码中,车和宝马是is-a的关系,即“宝马车”

如果用组合的话,就成了“宝马车”,会非常别扭

class tire{};
class car : public tire 
{class tire;//车有轮胎(构成has-a关系)
}

上述代码中,轮胎和车是has-a的关系,即“车轮胎”

这时就可以用组合

当然,如果两者都可以用的话,肯定优先用组合

相关文章:

【语法】C++的继承

目录 继承基本语法&#xff1a; protected访问限定符&#xff1a; 子类和父类之间的赋值兼容规则&#xff1a; 重定义(隐藏)&#xff1a; 继承中的友元/继承中的静态成员&#xff1a; 子类中的默认成员函数 构造函数/拷贝构造函数&#xff1a; 赋值重载函数&#xff…...

如何知道Ubuntu的端口是否被占用,被那个进程占用?如何终止进程

要检查Ubuntu系统中某个端口&#xff0c;比如5034&#xff0c;是否被占用及终止对应进程&#xff0c;请按以下步骤操作&#xff1a; 1. 检查端口占用情况 方法一&#xff1a;使用 lsof 命令 sudo lsof -i :5034输出结果会显示占用该端口的进程名、PID等信息。 方法二&#x…...

verdi使用tcl脚本批量添加波形

打开verdi console功能 在verdi的tools 里使能工具中的console功能; 在console执行tcl脚本 set cell_list { ts_0_lockup_latchn_clkc45_intno45811_i u_rst_scan_n_tp/u_scan_crl_reg/u_cell u_scan_crl_reg/u_cell u_scan_crl_reg/u_cell } ## specify the waveform window…...

【行业特化篇3】制造业简历优化指南:技术参数与标准化流程的关键词植入艺术

写在最前 作为一个中古程序猿,我有很多自己想做的事情,比如埋头苦干手搓一个低代码数据库设计平台(目前只针对写java的朋友),比如很喜欢帮身边的朋友看看简历,讲讲面试技巧,毕竟工作这么多年,也做到过高管,有很多面人经历,意见还算有用,大家基本都能拿到想要的offe…...

oracle怎样通过固化较优执行计划来优化慢sql

一 问题描述 有次生产环境cpu使用率增高&#xff0c;ADDM报告提示某条sql比较耗费cpu&#xff1a; 提示&#xff1a; 在分析期间, 此 SQL 语句至少利用了 6 个不同的执行计划 #查看该sql都有哪些执行计划 SELECT * FROM table(DBMS_XPLAN.DISPLAY_AWR(sqlid值)); 我手动执…...

【无标题】好用的远程链接插件

现在在做后端开发有的时候需要链接到远程服务器,有很多插件看不到整体的目录结构 推荐 trae的 ssh Client 有很清晰的目录结构...

Plant Simulation MultiPortalCrane Store 小案例

一个天车从库区移动商品到指定地点的案例 库区商品&#xff1a;库区上随机位置摆放商品&#xff0c;在源上绑定方法&#xff08;应该也可以直接在库区上生成&#xff0c;我这里是使用源可以改变生成多少个商品&#xff09; // 源的self.OnExit var Store : object : 存储 var …...

MyBatis 使用 POJO 参数动态查询教程

项目结构概览&#xff08;基于图片描述&#xff09;&#xff1a; mybatis02 ├─ src/main/java │ └─ cn.cjxy │ ├─ domain # 实体类&#xff08;如 Emp.java&#xff09; │ ├─ mapper # Mapper 接口&#xff08;如 EmpMapper.java&#xff09; │…...

【MCP Node.js SDK 全栈进阶指南】高级篇(5):MCP之微服务架构

引言 在软件架构中,微服务模式已成为构建可扩展系统的主流方案。 将MCP与微服务架构结合,能够为AI驱动的应用带来显著优势。 本文将探讨如何在微服务环境中集成和部署MCP服务,以及如何利用云原生技术实现高可用、高性能的MCP应用。 目录 MCP在微服务中的角色服务网格集成容…...

UBUS 通信接口的使用——添加一个object对象(ubus call)

1&#xff0c;引入 ubus提供了一种多进程通信的机制。存在一个守护进程ubusd&#xff0c;所以进程都注册到ubusd&#xff0c;ubusd进行消息的接收、分发管理。 ubus对多线程支持的不好&#xff0c;例如在多个线程中去请求同一个服务&#xff0c;就有可能出现不可预知的结果。 …...

强化学习贝尔曼方程推导

引言 强化学习中贝尔曼方程的重要性就不说了&#xff0c;本文利用高中生都能看懂的数学知识推导贝尔曼方程。 回报 折扣回报 G t G_t Gt​的定义为&#xff1a; G t R t 1 γ R t 2 γ 2 R t 3 ⋯ ∑ k 0 ∞ γ k R t k 1 (1) G_t R_{t1} \gamma R_{t2} \gamm…...

【MCP Node.js SDK 全栈进阶指南】高级篇(2):MCP高性能服务优化

前言 随着MCP应用规模的扩大和用户量的增加,性能优化成为系统稳定运行的关键因素。高性能的MCP服务不仅能提供更好的用户体验,还能降低运营成本,提高系统的可扩展性。本文将深入探讨MCP TypeScript-SDK的性能优化策略,帮助开发者构建高效、稳定的MCP服务。 1. 性能瓶颈识…...

图片识别为提示词,背景信息提取 -从头设计数字生命第7课, demucs——仙盟创梦IDE

1. 图像内容理解与标注 用途&#xff1a;在大规模图像数据集的整理和标注工作中&#xff0c;通过特定提示词可引导图片识别系统更准确地提取图像中的背景信息&#xff0c;并进行标注。例如在医学图像库标注中&#xff0c;使用 “疾病相关背景特征” 作为提示词&#xff0c;系统…...

域对齐是什么

域对齐&#xff08;Domain Alignment&#xff09;是在机器学习和计算机视觉等领域中常用的技术 定义 域对齐旨在将不同域&#xff08;Domain&#xff09;的数据映射到一个共同的特征空间中&#xff0c;使得来自不同域的数据在该空间中具有相似的分布。这里的“域”可以指代不…...

opencv 直方图均衡化

直方图均衡化 1. 啥叫直方图2. 绘制直方图3. 直方图均衡化3.1 自适应直方图均衡化&#xff08;cv2.equalizeHist()&#xff09;3.2 对比度受限的自适应直方图均衡化(cv2.createCLAHE()) 1. 啥叫直方图 直方图是对数据进行统计的一种方法&#xff0c;并且将统计值组织到一系列实…...

JDK 8 函数式接口全集

JDK 8 函数式接口全集 函数式接口如何定义关于注解 FunctionalInterface 函数式接口的分类与简单使用生产型接口 Supplier使用 消费型接口 Consumer使用 ​​函数型接口&#xff08;Function&#xff09;​​实例(合并字符串) ​​断言型接口&#xff08;Predicate&#xff09;…...

网站防护无惧DDoS攻击:2025年实战指南

在数字化时代&#xff0c;DDoS攻击已成为企业生存的“生死线”。2024年全球日均攻击峰值突破5.4Tbps&#xff08;Cloudflare数据&#xff09;&#xff0c;电商、金融行业更是重灾区。本文将结合最新技术趋势和实战案例&#xff0c;为你提供一套低成本、高可靠的防御方案。 一、…...

【AI论文】BitNet v2:针对1位LLM的原生4位激活和哈达玛变换

摘要&#xff1a;激活异常值阻碍了1位大型语言模型&#xff08;LLM&#xff09;的有效部署&#xff0c;这使得低比特宽度的量化变得复杂。 我们介绍了BitNet v2&#xff0c;这是一个新的框架&#xff0c;支持1位LLM的原生4位激活量化。 为了解决注意力和前馈网络激活中的异常值…...

windows 使用 FFmpeg 放大视频原声

问题&#xff1a;原视频声音太小&#xff0c;就算把视频音量调到最大&#xff0c;声音也听不太清 一、下载 下载地址&#xff1a;Download FFmpeg 根据需要选择合适版本下载解压&#xff0c;如浏览器下载速度慢&#xff0c;可使用迅雷下载 二、配置环境变量 1.把解压的文件放…...

RHCE第七章:SElinux

一、SElinux SELinux 是一套安全策略系统 1.作用&#xff1a; &#xff08;1&#xff09;SELinux 域限制&#xff1a;对服务程序的功能进行限制&#xff0c;以确保服务程序做不了出格的事 &#xff08;2&#xff09;SELinux 安全上下文&#xff1a;对文件资源的访问限制&am…...

一文简单记录打通K8s+Kibana流程如何启动(Windows下的Docker版本)

为ES和Kibana组建Docker网络 docker network create elastic下载8.18.0版本镜像Es并启动 docker run --name es-node01 --net elastic -p 9200:9200 -p 9300:9300 -t docker.elastic.co/elasticsearch/elasticsearch:8.18.0启动Kibana&#xff08;简单一些直接咯和ES对应版本…...

【系统参数合法性校验】spring-boot-starter-validation

JSR303校验 统一校验的需求 前端请求后端接口传输参数&#xff0c;是在controller中校验还是在Service中校验&#xff1f; 答案是都需要校验&#xff0c;只是分工不同。 Contoller中校验请求参数的合法性&#xff0c;包括&#xff1a;必填项校验&#xff0c;数据格式校验&…...

蓝桥杯 10. 凯撒加密

凯撒加密 原题目链接 题目描述 给定一个单词&#xff0c;请使用凯撒密码将这个单词加密。 凯撒密码是一种替换加密的技术&#xff0c;单词中的所有字母都在字母表上向后偏移 3 位后被替换成密文。 即&#xff1a; a → db → e⋯w → zx → ay → bz → c 输入描述 输入…...

Discord多账号注册登录:如何同时管理多个账户?

Discord是许多人、特别是游戏玩家和社区管理者的重要沟通工具。随着用户需求的增长&#xff0c;越来越多的人开始在Discord上注册多个账号进行管理。例如&#xff0c;个人和工作账号的区分&#xff0c;多个游戏社区的参与&#xff0c;或者通过不同的身份进行更灵活的社交互动。…...

Harbor默认Redis与Notary组件弱口令漏洞分析与修复指南

一、 背景 某资源池控制面和运行面生产环境部署的harbor被漏扫出弱口令需要进行整改&#xff0c;主要涉及 default、server、signer用户存在弱口令。 二、 分析与处理 首先需求确认这三个用户是harbor那个组件使用&#xff0c;最好确认的是default这个用户&#xff0c;它是r…...

【Prometheus-Postgres Exporter安装配置指南,开机自启】

目录 内容概述 一、安装步骤1. 安装 PostgreSQL Exporter2. 创建 PostgreSQL 监控用户3. 配置 Systemd 服务4. 启动并验证服务5. 集成到 Prometheus 内容概述 本教程详细指导如何安装 PostgreSQL Exporter&#xff08;版本 0.15.0&#xff09;&#xff0c;包括&#xff1a; 软…...

leetcode:3005. 最大频率元素计数(python3解法)

难度&#xff1a;简单 给你一个由 正整数 组成的数组 nums 。 返回数组 nums 中所有具有 最大 频率的元素的 总频率 。 元素的 频率 是指该元素在数组中出现的次数。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,2,3,1,4] 输出&#xff1a;4 解释&#xff1a;元素 1 和 2 的…...

论文导读 - 基于特征融合的电子鼻多任务深度学习模型研究

基于特征融合的电子鼻多任务深度学习模型研究 原论文地址&#xff1a;https://www.sciencedirect.com/science/article/pii/S0925400524009365 引用此论文&#xff08;GB/T 7714-2015&#xff09;&#xff1a; NI W, WANG T, WU Y, et al. Multi-task deep learning model f…...

VSCode突然连接不上服务器(已解决)

可恶&#xff0c;不知道昨天还好好的VSCode还可以连接到服务器&#xff0c;今天打开就连接不上了&#xff0c;搜了一圈很多都说是服务端的vscode-server这个文件里面保存的commitID与当前我们VSCode上的ID不一致导致连接失败&#xff08;据说是因为VSCode自动更新导致的&#x…...

解决Ollama run qwen3:32b: Error: unable to load model问题

问题描述 在尝试使用Ollama部署Qwen3模型时&#xff0c;许多用户遇到了以下错误&#xff1a; ollama run qwen3:32b Error: unable to load model: /Users/xxxx/.ollama/models/blobs/sha256-3291abe70f16ee9682de7bfae08db5373ea9d6497e614aaad63340ad421d6312这个错误通常会…...

C++ 单例对象自动释放(保姆级讲解)

目录 单例对象自动释放&#xff08;重点*&#xff09; 方式一&#xff1a;利用另一个对象的生命周期管理资源 方式二&#xff1a;嵌套类 静态对象&#xff08;重点&#xff09; 方式三&#xff1a;atexit destroy 方式四&#xff1a;atexit pthread_once 单例对象自动释…...

李录谈卖出股票的时机:价值投资的动态决策框架

作为最贴近芒格与巴菲特投资理念的中国投资人&#xff0c;李录对卖出时机的思考融合了价值投资的核心逻辑与实战经验。通过其在哥伦比亚大学的多场演讲及访谈&#xff08;主要集中于2006年、2013年及后续公开内容&#xff09;&#xff0c;我们可以将其观点归纳为以下五个维度&a…...

Docker的简单使用(不全)

Docker Hello World Docker 允许在容器内运行应用程序&#xff0c;使用docker run命令来在容器内运行一个应用程序 输出Hello World runoobrunoob:~$ docker run ubuntu:15.10 /bin/echo "Hello world"Hello world docker&#xff1a;Docker的二进制执行文件 run…...

A2A与MCP:理解它们的区别以及何时使用

随着AI不断深入到商业工作流中&#xff0c;多个AI代理&#xff08;Agent&#xff09;之间的无缝协作成为了一个主要挑战。 为了解决这个问题&#xff0c;Google Cloud推出了一种名为Agent2Agent&#xff08;A2A&#xff09;的开放协议&#xff0c;旨在使不同平台和系统中的AI代…...

AI Agent开源技术栈

构建和编排Agent的框架 如果您是从头开始构建&#xff0c;请从这里开始。这些工具可以帮助您构建Agent的逻辑——做什么、何时做以及如何处理工具。您可以将其视为将原始语言模型转化为更自主的模型的核心大脑。 2. 计算机和浏览器的使用 一旦你的Agent能够规划&#xff0c…...

判断用户选择的Excel单元格区域是否跨页?

VBA应用程序开发过程中&#xff0c;经常需要处理用户选中的单元格区域&#xff0c;有的应用场景中&#xff0c;需要限制用户选中区域位于同一页中&#xff08;以打印预览显示的分页划分&#xff09;&#xff0c;但是VBA对象模型中并没有提供相应的接口&#xff0c;用于快速查询…...

驱动开发硬核特训 · Day 24(上篇):走进Linux内核时钟子系统 —— 硬件基础全解析

一、前言 在 SoC&#xff08;System on Chip&#xff09;设计中&#xff0c;“时钟&#xff08;Clock&#xff09;”不仅是信号同步的基石&#xff0c;也是各个模块协调运作的前提。没有合理的时钟体系&#xff0c;CPU无法运行&#xff0c;外设无法通信&#xff0c;存储器无法…...

【GPU 微架构技术】Pending Request Table(PRT)技术详解

PRT&#xff08;Pending Request Table&#xff09;是 GPU 中用于管理 未完成内存请求&#xff08;outstanding memory requests&#xff09;的一种硬件结构&#xff0c;旨在高效处理大规模并行线程的内存访问需求。与传统的 MSHR&#xff08;Miss Status Handling Registers&a…...

角度(degrees)和弧度(radians)转换关系

目录 1.从角度转换到弧度&#xff1a; 2.从弧度转换到角度&#xff1a; 示例 将90度转换为弧度&#xff1a; 将π/3​弧度转换为角度&#xff1a; 角度&#xff08;degrees&#xff09;和弧度&#xff08;radians&#xff09;之间的转换关系可以通过以下公式来实现&#xff…...

【大语言模型DeepSeek+ChatGPT+GIS+Python】AI大语言模型驱动的地质灾害全流程智能防治:风险评估、易发性分析与灾后重建多技术融合应用

地质灾害是指全球地壳自然地质演化过程中&#xff0c;由于地球内动力、外动力或者人为地质动力作用下导致的自然地质和人类的自然灾害突发事件。在降水、地震等自然诱因的作用下&#xff0c;地质灾害在全球范围内频繁发生。我国不仅常见滑坡灾害&#xff0c;还包括崩塌、泥石流…...

第十六届蓝桥杯 2025 C/C++组 25之和

目录 题目&#xff1a; 题目描述&#xff1a; 题目链接&#xff1a; 思路&#xff1a; 思路详解&#xff1a; 代码&#xff1a; 代码详解&#xff1a; 题目&#xff1a; 题目描述&#xff1a; 题目链接&#xff1a; P12339 [蓝桥杯 2025 省 B/Python B 第二场] 25 之和…...

万界星空科技QMS质量管理系统几大核心功能详解

QMS质量管理系统&#xff08;Quality Management System&#xff09;是一款专为现代企业设计的、全面且高效的质量管理工具&#xff0c;融合了现代质量管理理念与前沿的信息技术&#xff0c;旨在帮助企业构建完善的质量管理体系&#xff0c;确保产品和服务质量。以下为你详细介…...

SSR同构渲染深度解析

同构渲染&#xff08;Isomorphic Rendering&#xff09;是SSR&#xff08;服务器端渲染&#xff09;的核心概念&#xff0c;指同一套代码既能在服务器端运行&#xff0c;也能在客户端运行。下面我将从原理到实践全面介绍SSR同构渲染。 一、同构渲染核心原理 1. 基本工作流程 …...

【论文阅读/复现】RT-DETR的网络结构/训练/推理/验证/导出模型

利用ultralytics仓库&#xff0c;复现RT-DETR官方实验环境。 使用基于ResNet50和ResNet101的RT-DETR。 目录 一 RT-DETR的网络结构 1 编码器结构 2 RT-DETR 3 CCFF中的融合块 4 实验结果 二 RT-DETR的安装/训练/推理/验证/导出模型 1 安装 2 配置文件 3 训练 4 推理 …...

KUKA机器人关机时冷启动介绍

KUKA机器人在正常关机时&#xff0c;可以从示教器上操作。在示教器上操作时需要选择“冷启动”方式关闭计算机。等示教器屏幕关闭之后&#xff0c;再把主开关旋钮关闭。 一、先登录【管理员】权限&#xff0c;再在【主菜单】下选择【关机】。 二、在关机的默认中&#xff0c;…...

MCP Java SDK 介绍与使用指南

MCP与MCP Java SDK 概念 MCP 是什么&#xff1f; 模型上下文协议&#xff08;Model Context Protocol, MCP&#xff09;是用于标准化AI模型与工具间通信的规范。通过定义通用接口&#xff0c;确保不同AI组件&#xff08;如模型推理服务、工具插件&#xff09;能无缝协作。MCP …...

【Java核心】一文理解Java面向对象(超级详细!)

一&#xff1a;概述 1.1Java类及类的成员 属性、方法、构造器、代码块、内部类 1.2 面向对象的特征 封装、继承、多态&#xff08;抽象&#xff09; 1.3 其它关键字的使用 This、super、package、import、static、final、interface、abstract 1.4 面向对象和面向过程 &…...

2025年DDoS攻击防御全解析:应对超大流量的实战策略

一、2025年DDoS攻击的新趋势 超大规模攻击常态化&#xff1a;攻击流量突破300Gbps&#xff0c;部分案例甚至达到T级规模&#xff0c;传统单点防御已无法应对。 混合攻击模式盛行&#xff1a;攻击者结合应用层&#xff08;HTTP Flood、CC攻击&#xff09;与网络层&#xff08;U…...

【动态导通电阻】 GaN PiN二极管电导调制对动态 RON 的影响

2020 年,浙江大学电气工程学院的Shaowen Han等人采用实验研究的方法,对垂直 GaN-on-GaN PiN 二极管中电导调制的瞬态行为及其对动态导通电阻(RON)的影响进行了深入探究。他们基于高质量的 GaN 基板开发的垂直 GaN-on-GaN 功率器件具有高电流容量和高击穿电压等优势,而与间…...

第十六届蓝桥杯 2025 C/C++B组第一轮省赛 全部题解(未完结)

目录 前言&#xff1a; 试题A&#xff1a;移动距离 试题C&#xff1a;可分解的正整数 试题D&#xff1a;产值调整 试题E&#xff1a;画展布置 前言&#xff1a; 我参加的是第一轮省赛&#xff0c;说实话第一次参加还是比较紧张的&#xff0c;真到考场上看啥都想打暴力&…...