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

从父类到子类:C++ 继承的奇妙旅程(1)

前言:

        在前文,小编讲述了C++模板的进阶内容,下面我们就要结束C++初阶的旅行,开始进入C++进阶容的旅c程,今天旅程的第一站就是C++三大特性之一——继承的旅程,各位扶好扶手,开始我们今天的C++继承的奇妙旅程。

1.继承的概念和定义

1.1.继承的概念

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

        可能很多读者朋友会好奇继承设计出来的目的是什么,下面我通过一个简单的例子就可以说明为什么继承会被设计出来,我们在进入学校的一些建筑例如图书馆,实验室等等都需要进行身份识别,而学校里不仅仅就只有学生,还有老师,所以我们涉及出两个类来帮助我们记录学生和老师的信息,如下代码所示:

class Student
{public://不重要就不写了protected:  //对于这里为什么用protected而不是用private,等会我会解释string _name = "忘梓."; // 姓名string _address; // 家庭地址int _age = 20; // 年龄int _stuid; // 学号
};
class Teacher
{public://不重要protected:string _name = "小李子"; // 姓名int _age = 18; // 年龄string _address; // 地址string _title; // 工号
};

        通过上面小编对于两个类的书写,可能很多读者朋友感觉到了一个点,那就是两个类涉及了很多相似内容,就比如姓名,年龄,地址,电话,这四个都是两个类公有的,只有学号和工号是二者分别特有的,不得不说,这样写起来会感到有一些冗余,现在只有两个类还好,但之后我们如果想要写一个比较大一点的项目的话,我们就会书写很多个类,这些类可能会出现上面的情况,我们如果分别书写的话,就大大减少了我们写代码的效率,作为一个程序猿,保证效率高效是很重要的,所以此时C++的祖师爷就推出了继承这个概念(感觉这么说也不对,因为继承是面向对象语言公有的,但是这么说的话也有一定道理),继承就是为了解决这种重复出现的成员变量或者函数而生的,下面小编就讲述一下我们如何用继承来解决上述问题。

        针对这种问题,我们可以把两个类公共的成员放到Person类里面,Student类和Teacher类都可以继承它,就可以复用这些成员,无须在每个类里面重复定义了,省去了许多的麻烦,虽然小编还没有说继承具体怎么用,但我先给各位展示一下它的用法:

class Person
{protected:string _name = "忘梓"; // 姓名int _age = 18; // 年龄string _address; // 地址
};
​
class Student : public Person  //至于为什么这么写,我后面会进行解释。
{private:int _stuid; // 学号
};
​
class Teacher : public Person
{private:string _title //工号
};

1.2.继承的定义

1.2.1.定义的格式

        如上图所示,我们可以知道Student是派生类,public是继承方式,继承方式也分为三种,等会小编讲述的时候再给各位展开,Person就是基类,因为翻译的原因,有时候把派生类也叫做子类,基类也叫做父类,毕竟子承父类,就比如小编标题就这么讲述的,但是在本文中我还是会用派生类和基类来给各位讲述,因为在很多地方都是用这两个名称来论述的,下面小编着重说一下在继承中基类成员访问方式的变化(这里比较复杂)。

        首先我们需要把继承方式和访问限定符两个概念区分开,后者是之前小编在C++的初次见面中讲到过的,它就是我们日常写类的时候使用到的特殊词,它的作用就是限定之后我们实例化对象之后对象可以访问到的类中间的方法或者成员等等;而前者是我们接下来要讲到的。

1.2.2.继承基类成员访问方式的变化

        通过上表我们就可以知晓继承方式的复杂程度,可能大多数读者朋友看到这个图的时候都感到吃力,因为它看上去很复杂,因为它是继承方式和访问限定符的“杂交版”,子类在继承父类的时候,因为继承方式的不同从而导致访问限定符会发生改变。可能有些读者的C++老师要求背过这张表的,以我看来,这样的方式是不可取的,因为死记硬背不可取,短时间内是记住了,但如果不知道原理加上长时间不用,这个很快就会忘记的(PS:虽然长时间不看也是会忘掉的,但是通过短暂几分钟的回想是会想起来这部分内容的)。下面我将会以比较简单的方式帮助各位“记忆这张表”。

        1.基类private成员在派生类中无论以什么方式继承都是不可见的。这里的不可见是指基类的私有成员还是被继承到派生类对象中,但是语法上限制了派生类对象不管是在类里面还是在类外面都不能访问它。所以说小编不建议各位以后用继承关系的时候,用private访问限定符,除非是真的想把内容保护起来,那就可以使用private限定符了,但此时读者朋友想知道,如果我不使用private类,那岂不是对象可以肆意妄为的去访问我的成员了?NONONO,可能有一个访问限定符被读者忘掉了,那就是:protected,它第一次出现的时候,我是这么说的:

        2.基类private成员在派生类中是不可以被访问,如果基类成员不想在类外直接被访问。但需要在派生类中能访问,就定义为protected。可以看出保护成员限定符是因为继承在出现的。这也算是把之前埋下的伏笔收回了(PS:我之前写的博客错别字是真的逆天,而且现在回看好羞耻...)

        3.实际上上面的表格我们进行一下总结会发现,基类的私有成员在派生类都是不可见的。基类的其他成员在派生类的访问方式==Min(成员在基类的访问限定符,继承方式)。public->protected->private。这个是记住这个表至关重要的方式,因为它真的很好理解,就拿第一列为例:基类的public成员和继承方式public取最小值就是public;基类的protected成员和继承方式public取最小是就是protected,所以基类的protected的成员就是子类的protected成员;private成员不在这个关系中,它默认子类就是不可见的。所以说这样记忆十分的方便,并且更容易记住。

        4.使用关键字class默认的继承方式是private,使用struct时默认的继承方式是public。不过最好显示的写出继承方式 。这个我之前说过,就不细说了,养成习惯就好了。

        5.在实际运用中一般使用的都是public继承,几乎很少使用protected/private继承,也不提倡使用他们。因为这样做继承下来的成员只能在派生类的类里面使用,实际中扩展维护性是不强的。

        光文字说我自认为很干巴,所以下面我用一个代码来简单的说一下上面的讲解。

// 实例演⽰三种继承关系下基类成员的各类型成员访问关系的变化
class Person
{
public:void Print(){cout << _name << endl;}
protected:string _name; // 姓名
private:int _age; // 年龄
};
//class Student : protected Person
//class Student : private Person
class Student : public Person
{
protected:int _stunum; // 学号
};

        经过上面代码的测试就可以知道继承关系和成员限定符的关系~这里小编就不自行测试了,有兴趣的读者朋友可以自己测试一下,特别是对Person中的_age的测试,看看你究竟可以不可以使用它,不过我相信测试完以后的读者朋友会出现下面的报错:

        这样就可以证明1的结论是正确的,其他的自行测试即可。

1.3.继承类模版

        类模版也是可以进行继承的,这里小编就拿之前我们曾经实现的栈的模拟实现举例,下面是通过继承实现的栈:

namespace wang
{//template<class T>//class vector//{};// stack和vector的关系,既符合is-a,也符合has-atemplate<class T>class stack : public std::vector<T>{public:void push(const T& x){// 基类是类模板时,需要指定⼀下类域,// 否则编译报错:error C3861: “push_back”: 找不到标识符vector<T>::push_back(x);}void pop(){vector<T>::pop_back();}const T& top(){return vector<T>::back();}bool empty(){return vector<T>::empty();}};
} 

        上面是通过继承实现的栈,小编直接用的组合的方式来进行,可能有一些读者搞不懂什么是继承,什么是组合,下面小编先来简单的阐述一下:

1. 继承(Inheritance)
概念
  • 继承表示"is-a"关系,即子类是父类的一种特化。

  • 子类继承父类的属性和方法,并可以扩展或重写父类的行为。

  • 支持多态(通过虚函数实现)。

语法示例
class Animal {
public:virtual void speak() { cout << "Animal sound" << endl; }
};
​
class Dog : public Animal { // Dog 是 Animal 的子类
public:void speak() override { cout << "Woof!" << endl; }
};
优点
  • 代码复用:子类可以直接复用父类的代码。

  • 多态性:通过基类指针/引用调用子类方法。

  • 天然表达分类关系(如 Dog 是一种 Animal)。

缺点
  • 高耦合:父类修改可能影响所有子类。

  • 可能导致复杂的类层次结构(过度继承)。

适用场景
  • 当需要表达明确的分类层次(如 CircleShape)。

  • 需要利用多态特性时(如通过基类统一管理不同子类对象)。


2. 组合(Composition)
概念
  • 组合表示"has-a"关系,即一个类包含另一个类的实例作为成员。

  • 通过将对象作为成员变量使用,实现功能的复用。

语法示例
class Engine {
public:void start() { cout << "Engine started" << endl; }
};
​
class Car {
private:Engine engine;  // Car 包含 Engine 的实例
public:void startCar() { engine.start(); }
};
优点
  • 低耦合:内部类的修改不会直接影响外部类。

  • 灵活性高:可动态更换成员对象(如通过接口或指针)。

  • 符合单一职责原则:每个类专注于单一功能。

缺点
  • 需要显式调用成员对象的方法(需要手动委托)。

  • 可能增加代码量。

适用场景
  • 表达部分与整体的关系(如 Car 包含 Engine)。

  • 需要动态替换组件时(如游戏角色装备不同武器)。

  • 优先选择组合以避免继承的耦合问题。


关键对比

继承组合
关系类型"is-a""has-a"
耦合度高(父类与子类紧密关联)低(通过接口或成员对象交互)
灵活性较低(需通过继承扩展)高(可替换成员对象)
多态支持(之后会讲)天然支持(虚函数)需依赖接口或抽象类
设计原则符合Liskov替换原则符合合成复用原则

        以上就是继承和组合的关系,简单来说,当我们不使用实例化对象进行类的书写的时候,我们使用的是继承的方法,这就是is-a,如果使用了实例化对象作为成员变量,那么这个就是组合,这就是has-a,各位理解好这个点就好。

        可能很多读者朋友会很奇怪,为什么我使用基类的函数时,我需要表明类域,因为stack<int>实例化时,也实例化vector<int>了,但是模版是按需实例化,push_back等成员函数未实例化,所以找不到。简单来说,vector是实例化出来了,但是其内容并没有实例化出来,也就是说它是由外在,内在还没有展现出来,这就是为什么我需要表明类域。

        相信不少读者觉着这么写比较简单(当然还有认为复杂的,这是正常的,因为每个人都有每个人自己的想法),不过小编并不推荐这个方法进行一些功能的实现,具体原因我会在继承和组合的对比中进行讲述,各位先明白这个点就好。

2.基类和派生类的转换

        public继承的派生类对象可以赋值给基类的指针/基类的引用。这里有个比较形象的说法,可以把它称之为切片或者是切割。寓意把派生类中基类的那部分切出来,基类指针或者引用指向的是派生类切出来的部分。如下图所示:

        上图就可以形象的表示什么是“切割”,下面我简单的通过几句代码介绍它的用法:

class Person
{
protected :string _name; // 姓名string _sex; // 性别int _age; // 年龄
};
class Student : public Person
{
public :int _No ; // 学号
};
int main()
{Student sobj ;// 1.派⽣类对象可以赋值给基类的指针/引⽤Person* pp = &sobj;Person& rp = sobj;// 派生类对象可以赋值给基类的对象是通过调⽤后⾯会讲解的基类的拷贝构造完成的Person pobj = sobj;  //这里也是把基类中的父类的成员函数切割给了基类//2.基类对象不能赋值给派⽣类对象,这⾥会编译报错sobj = pobj;return 0;
}

        上面的代码就阐述了我们如何使用切割来进行基类和派生类之间的转换,可能有些读者会疑问:为什么会有这个转换呢?这和我们之后讲解的多态有关,详细内容敬请期待我之后的多态的博客。

        基类的指针或者引用可以通过强制类型转换赋值给派生类的指针或者是引用,但是必须是基类的指针是指向派生类对象时才是安全的。这里的基类如果是多态类型的话,可以使用RTTI(Run-Time Type Information)的dynamic_cast 来进行识别后进行安全转换。(这要等着后面的类型转换的博客,那里会进行会专门的讲解,小小的埋下伏笔)。

        以上就是基类和派生类之间的转换,下面我来简单的阐述一下本篇博客的最后一部分内容:继承中的作用域。

3.继承中的作用域

3.1.隐藏规则

        1.在继承中基类和派生类都有独特的作用域,这里常常会让一些读者摸不清头脑,因为有的读者会认为,当派生类继承基类的时候,理所应当基类的内容也是包含在派生类的作用域中,这样的观点是错误的。虽然派生类可以访问基类的成员(取决于继承方式和访问权限),但这并不意味着基类的作用域被直接“合并”到了派生类的作用域中。它们的成员查找规则遵循分层作用域模型,理解这一点能避免许多常见的编程错误。就比如上面的代码可以分为这两层:

        2.派生类和基类中有同名成员,派生类讲屏蔽基类对同名成员的直接访问,这样的情况叫做隐藏。如果想要使用基类成员时,可以使用基类:基类成员 显示的进行访问,如果直接使用成员的话,默认会直接用派生类的成员,下面我将用一个代码解释这一个特性:

class Person
{
public:Person():_age(12){}
protected:int _age;
};
class Student : public Person
{
public:void Print(){cout << _age << endl;}
protected:int _age = 13;
};
int main()
{Student s1;s1.Print();  //猜猜会打印出什么return 0;
}

        上面的代码就展现了派生类对同名的成员变量进行的隐藏,它是会优先去调用自己作用域的成员变量,如果想要使用基类的成员变量,那么可以用下面的方法,即可使用基类的成员变量。

//上面代码的局部代码
void Print()
{cout << _age << endl;cout << Person::_age << endl;
}

        3.需要注意的是如果是对于成员函数的隐藏,只需要函数名相同就可以构成隐藏.。这里需要和之前学习的函数的重载区分一下,函数的重载是在同一个作用域的,而隐藏是在不同作用域的,这点各位要知晓,下面我继续写一个示范让各位知晓成员函数隐藏。

class Person
{
public:Person():_age(12){}void Print(){cout << _age << endl;}
protected:int _age;
};
class Student : public Person
{
public:void Print(){cout << _age << endl;}
protected:int _age = 13;
};
int main()
{Student s1;s1.Print();  //对于派生类成员函数的使用s1.Person::Print(); //对于基类成员函数的使用return 0;
}

        和成员变量一样,我们想要使用基类的成员函数,只有指明类域才可以使用基类的成员函数,才可以把隐藏破除。

        4.注意在实际的继承体系中最好不要定义同名的成员。因为这样会让工程的复杂度提高,我们如果基类和派生类使用的是同名的函数,那么我们如果想要使用基类的成员函数会比较复杂,就比如上面的代码,我们需要指明类域,可能在一些简单的代码看不出来有什么不方便,不过以后我们接触的大型工程的代码肯定有上万行代码起步,如果有时候想要调用父类的成员函数的时候忘记指明类域了,那么找起错来就很难受了~

3.2.考察继承作用域的几个小题

1.A和B类中的两个func构成什么关系()

A.重载 B.隐藏 C.没关系

class A
{
public:void func(){cout << "func()" << endl;}
};
class B : public A
{
public:void func(int i){cout << "func(int i)" <<i<<endl;}
};

        这个题其实很容易,因为我刚刚讲了什么是隐藏关系,观察A和B类的func函数,可以知晓一个来自基类,属于基类作用域;一个来自派生类,属于派生类的作用域;这是构成隐藏的第一个条件,并且它们的函数名相同,这就达成了第二个条件,所以构成了隐藏的关系。这个题目自然选择B.隐藏

2.下面的程序的编译运行结果是什么()

A.编译报错 B.运行报错 C.正常运行

//类的写法在上面
int main()
{B b;b.func(10);b.func();return 0;
};

        这个题目其实也是比较容易的,因为上一个题目刚说明了此时的func函数构成隐藏关系,此时的第一个语句是正确的,因为它符合了派生类中的func函数的定义,而第二个调用就不对了,因为如果想要使用基类成员函数,我们需要指明基类的类域,此时没有指明,默认的基类的成员函数被派生类隐藏了,所以此时相当于我们无中生有调用了func函数,既没有定义也没有声明,所以自然而然的,这个题目选择A.编译报错。

4.总结

【🌌小编的拖延症忏悔录】

        各位代码骑士们,这篇继承的奇妙漂流终于靠岸啦!不过说出来你们可能不信——这篇教程的诞生过程,简直比C++的编译错误还曲折!

        去年十月,我雄心壮志敲下第一行字,结果中途: 1️⃣ 被"拖延症Boss"连击KO 2️⃣ 在Linux森林里迷路三个月 3️⃣ 甚至偷偷跑去Python岛摸鱼(小声)

        直到最近复习C++时,突然被"Segmentation fault"现实暴击——好家伙,继承知识全还给祖师爷Bjarne了!于是连夜翻出这篇"祖传代码",边哭边补完了这个技术债(程序员の泪.jpg)

        ⚠️前方高能预警: 下期我们将勇闯《继承の黑暗森林》—— 🔸 钻石继承堪比迷宫 🔸 代码量像老板的需求一样膨胀

        不过别慌!本导游已备好: 🍵 提神咖啡 🐞 驱bug圣剑 💡 祖传防秃指南

        让我们相约下篇,继续在C++的星辰大海里浪到飞起!毕竟—— "程序员不摸鱼,和咸鱼有什么区别?"

(摸鱼归摸鱼,记得三连保命啊各位亲!)🐟✨

相关文章:

从父类到子类:C++ 继承的奇妙旅程(1)

前言&#xff1a; 在前文&#xff0c;小编讲述了C模板的进阶内容&#xff0c;下面我们就要结束C初阶的旅行&#xff0c;开始进入C进阶容的旅c程&#xff0c;今天旅程的第一站就是C三大特性之一——继承的旅程&#xff0c;各位扶好扶手&#xff0c;开始我们今天的C继承的奇妙旅程…...

HTML9:页面结构分析

页面结构分析 元素名描述header标题头部区域的内容&#xff08;用于页面或页面中的一块区域&#xff09;footer标记脚部区域的内容&#xff08;用于整个页面或页面的一块区域&#xff09;sectionWeb页面的一块独立区域article独立的文章内容aside相关的内容或应用&#xff08;…...

LabVIEW超声波液位计检定

在工业生产、运输和存储等环节&#xff0c;液位计的应用十分广泛&#xff0c;其中超声波液位计作为非接触式液位测量设备备受青睐。然而&#xff0c;传统立式水槽式液位计检定装置存在受建筑高度影响、量程范围受限、流程耗时长等问题&#xff0c;无法满足大量程超声波液位计的…...

maven 安装 本地 jar

命令&#xff1a; mvn install:install-file -DgroupIdnet.pingfang.application -DartifactIdjna -Dversion5.1.0 -Dpackagingjar -DfileD:\maven\repository1\jna\5.1.0\jna-5.1.0.jarmvn&#xff1a;这是Maven的执行命令。 install:install-file&#xff1a;这是Maven插件目…...

leetcode 141. Linked List Cycle

题目描述&#xff1a; 代码&#xff1a; 用哈希表也可以解决&#xff0c;但真正考察的是用快慢指针法。 /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode(int x) : val(x), next(NULL) {}* };*/ class Soluti…...

【Python】通过`Editable Install`模式详解,解决Python开发总是import出错的问题

摘要 田辛老师在很久以前&#xff0c;写过一篇关于Python的模块、包之间的内部关系的博客&#xff0c;叫做【Python】__init__.py 文件详解。 虽然我觉得这篇文章已经足够了&#xff0c; 但是还是有很多朋友碰到开发的过程中import包报错的问题。 今天&#xff0c; 田辛老师想…...

C 语言网络编程问题:E1696 无法打开 源 文件 “sys/socket.h“

#include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h>在 C 语言网络编程中&#xff0c;上述代码报如下错误 E1696 无法打开 源 文件 "sys/socket.h"E1696 无法打开 源 文件 "netinet/in.h" E1696 无法打开 源 文件…...

操作指南*

任务1: 环境搭建 1.1 创建Spring Boot项目 操作步骤&#xff1a; 使用IDEA创建项目&#xff1a; 打开IDEA → File → New → Project选择 Spring Initializr → 设置项目信息&#xff08;Group、Artifact、Java版本&#xff09;选择依赖&#xff1a;Spring Web、MySQL Drive…...

VRM Add-on for Blender 学习笔记

VRM Add-on for Blender 使用教程-CSDN博客 VRM Add-on for Blender 是 Blender 的一个官方插件&#xff0c;主要用于 导入和导出 VRM 格式的 3D 模型。VRM&#xff08;Virtual Reality Model&#xff09;是一种开放标准的 3D 人形角色模型格式&#xff0c;起源于日本&#xf…...

C++ 完美转发

C 完美转发逐步详解 1. 问题背景与核心目标 在 C 模板编程中&#xff0c;若直接将参数传递给其他函数&#xff0c;参数的 值类别&#xff08;左值/右值&#xff09;和 类型信息&#xff08;如 const&#xff09;可能会丢失。例如&#xff1a; template<typename T> voi…...

学习记录:DAY23

项目开发与学习记录&#xff1a;字段注入优化 前言 我总有一种什么大的要来了的危机感。还是尽快把项目做起来吧&#xff0c;现在全在弄底层的框架。这是一个两天的blog&#xff0c;前一天bug没修好&#xff0c;气到连blog都没写。 日程 5月7日 晚上7点&#xff1a;本来想玩…...

Linux 信号(下篇)

Linux 信号-CSDN博客&#xff08;上篇&#xff09; 前言&#xff1a;在我上一篇博客写到了信号产生的三种条件分别是键盘组合键、kill命令、系统调用接口&#xff1b; 接下来我要把信号产生剩余的两个条件介绍完毕并理解信号的保存&#xff0c;和信号从产生到保存到处理整个过…...

hadoop中的序列化和反序列化(1)

1. 什么是序列化和反序列化 序列化&#xff08;Serialization&#xff09; 是将对象的状态信息转换为可以存储或传输的格式的过程。序列化后的对象可以保存到文件中&#xff0c;或者通过网络传输。 反序列化&#xff08;Deserialization&#xff09; 是序列化的逆过程&#x…...

linux查java进程CPU高的原因

问题&#xff1a;linux查java进程CPU高的原因 解决&#xff1a;用jdk带的工具分析 被查的java最好也使用jdk启动 systemctl启动的注意要去掉PrivateTmptrue /opt/jdk1.8.0_441/bin/jps -l top -Hp 8156 printf "%x" 8533 /opt/jdk1.8.0_441/bin/jstack 8156 |…...

鸿蒙开发——3.ArkTS声明式开发:构建第一个ArkTS应用

鸿蒙开发——3.ArkTS声明式开发:构建第一个ArkTS应用 一、创建ArkTS工程二、ArkTS工程目录结构&#xff08;Stage模型&#xff09;三、构建第一个页面四、构建第二个页面五、实现页面之间的跳转六、模拟器运行 一、创建ArkTS工程 1、若首次打开DevEco Studio&#xff0c;请点击…...

vue3+ts的watch全解!

vue3中的watch只能监听以下四种数据&#xff1a; 1.ref定义的数据 2.reactive定义的数据 3.函数返回一个值&#xff08;getter函数&#xff09; 4.一个包含上述内容的数组 通常我们在使用watch的时候&#xff0c;通常会遇到以下几种情况&#xff1a; 情况一&#xff1a; …...

yarn的概述

1.Yarn的定义 2.Yarn的三大组件 3.Yarn的调度策略 1. YARN的定义 YARN&#xff08;Yet Another Resource Negotiator&#xff09; 是Hadoop生态系统中的一个资源管理框架&#xff0c;用于管理和调度集群中的计算资源。它允许多个应用程序在同一个集群上高效地运行&#xff0c;…...

C++初阶-string类4

目录 1.String operations 1.1string::c_str 1.2string::data 1.3string::copy 1.4string::find 1.5string::rfind 1.6string::find_first_of 1.7string::find_last_of 1.8string::find_first_not_of和string::find_last_not_of find_first_not_of 功能 典型用途 f…...

HarmonyOS NEXT深度解析:自研框架ArkUI-X的技术革命与跨平台实践

HarmonyOS NEXT&#xff5e;深度解析&#xff1a;自研框架ArkUI-X的技术革命与跨平台实践 引言&#xff1a;ArkUI-X的诞生背景与战略意义 在HarmonyOS NEXT全面摒弃AOSP代码的历史性转折点上&#xff0c;华为推出的ArkUI-X框架标志着国产操作系统研发进入深水区。根据华为202…...

CUDA:out of memory的解决方法(实测有效)

一、问题概述 1.问题分析 CUDA out of memory问题通常发生在深度学习训练过程中&#xff0c;当GPU的显存不足以容纳模型、输入数据以及中间计算结果时就会触发。这个问题可能由几个因素引起&#xff1a; 模型和数据规模&#xff1a;深度学习模型尤其是大型模…...

canal mysqltomysql增加同步的库操作

例如增加库 online 1、停止canal.adapter 服务。 ./bin/stop.sh2、备份数据库online&#xff0c;导入目标mysql 备份 mysqldump -h 127.0.0.1 -P 3307 --single-transaction -uroot -p -B online > online.sql导入 mysql -h 127.0.0.1 -P 3308 -uroot -p < onl…...

【AI】模型与权重的基本概念

在 ModelScope 平台上&#xff0c;「模型」和「权重」的定义与工程实践紧密结合&#xff0c;理解它们的区别需要从实际的文件结构和加载逻辑入手。以下是一个典型 ModelScope 模型仓库的组成及其概念解析&#xff1a; 1. ModelScope 模型仓库的典型结构 以 deepseek-ai/deepse…...

k8s 中 deployment 管理的多个 pod 构成集群吗

在 Kubernetes (k8s) 中&#xff0c;通过 Deployment 创建的多个 Pod 本身并不构成一个“集群”&#xff0c;而是属于同一个 工作负载&#xff08;Workload&#xff09; 的多个副本实例。它们的角色是 无状态服务副本&#xff0c;而非独立的集群节点。以下是详细解释&#xff1…...

「动态规划」线性DP:股票问题合集 / LeetCode 121|122|123|188 (C++)

目录 概述 Question1 思路 算法过程 Code 复杂度 Question2 思路 解题过程 Code 复杂度 Question3 思路 解题过程 Code 复杂度 Question4 思路 解题过程 Code 复杂度 总结 概述 我们已经了解过了线性DP&#xff1a; 「动态规划」线性DP&#xff1a;最长…...

【Python os模块完全指南】从基础到高效文件操作

目录 &#x1f31f; 前言&#x1f9e9; 技术背景与价值&#x1f6a7; 当前技术痛点&#x1f6e0;️ 解决方案概述&#x1f465; 目标读者说明 &#x1f4da; 一、技术原理剖析&#x1f3a8; 核心概念图解&#x1f4a1; 核心作用讲解&#x1f511; 关键技术模块说明⚖️ 技术选型…...

Ubuntu 安装 Keepalived、LVS

Keepalived Keepalived 是什么&#xff08;高可用&#xff09; Keepalived 是一个用于实现 高可用 性&#xff08;High Availability, HA&#xff09;的服务&#xff0c;是一款基于 VRRP 协议的高可用软件&#xff0c;常用于主备切换和虚拟IP漂移&#xff0c;在服务故障时自动…...

记录一个rabbitmq因为linux主机名服务无法启动的问题

https://g.co/gemini/share/fb5a55644f6f 过程因为主机名为数字导致之间无法进行网络访问&#xff0c;导致无法开启。修改主机名解决这一问题&#xff0c;debian在系统安装时会指定一个用户名&#xff0c;一般为IP地址的第一块&#xff0c;数字导致了无法访问。 #使用命令查看…...

打造个人知识库,wsl+ollama部署deepseek与vscode集成

目前大模型应用如火如荼,各大LLM如Deepseek也都提供了在线的助手服务,结合mcp-server还可以进一步拓展到本地的工具能力。 但对于一些和本地业务和数据强相关的资料,在线的大模型训练数据集一般并不能涵盖,特别还有一些敏感或对安全要求很高的数据,使用在线大模型并不现实…...

Spring 项目无法连接 MySQL:Nacos 配置误区排查与解决

在开发过程中&#xff0c;我们使用 Nacos 来管理 Spring Boot 项目的配置&#xff0c;其中包括数据库连接配置。然而&#xff0c;在实际操作中&#xff0c;由于一些概念的混淆&#xff0c;我们遇到了一些连接问题。本文将分享我的故障排查过程&#xff0c;帮助大家避免类似的错…...

P值、置信度与置信区间的关系:统计推断的三大支柱

目录 引言一、P值是什么&#xff1f;——假设检验的“证据强度”1.1 定义1.2 判断标准&#xff1a;显著性水平 α \alpha α&#xff08;阿尔法&#xff09;1.3 示例说明 二、置信区间与置信度&#xff1a;参数估计的“不确定性范围”2.1 置信区间的定义2.2 置信度的含义 三、显…...

探索智能仓颉:Cangjie Magic开发体验

探索智能仓颉:Cangjie Magic 的开发体验与技术革新 在大型语言模型(LLM)驱动的智能体开发领域,2025年3月开源的 Cangjie Magic 以其独特的原生仓颉语言基因和三大核心技术突破,为开发者提供了一种全新的开发范式。本文将从技术架构、实际应用、开发体验及未来潜力等角度,…...

$在R语言中的作用

在 R 语言中&#xff0c;$ 是一个非常重要的操作符&#xff0c;主要用于访问对象的成员或组件。它的用途非常广泛&#xff0c;不仅限于数据框&#xff08;data frame&#xff09;&#xff0c;还可以用于列表&#xff08;list&#xff09;、环境&#xff08;environment&#xf…...

【Pandas】pandas DataFrame rolling

Pandas2.2 DataFrame Function application, GroupBy & window 方法描述DataFrame.apply(func[, axis, raw, …])用于沿 DataFrame 的轴&#xff08;行或列&#xff09;应用一个函数DataFrame.map(func[, na_action])用于对 DataFrame 的每个元素应用一个函数DataFrame.a…...

新疆地区主要灾害链总结

新疆地处亚欧大陆腹地,拥有高山(如天山、昆仑山)、盆地(如塔里木盆地、准噶尔盆地)、沙漠(如塔克拉玛干沙漠)、绿洲、内陆河流和冰川等复杂多样的地貌单元。其气候极端,干旱少雨是常态,但山区夏季暴雨集中、冬季积雪深厚,地质构造活跃,地震风险高。这些特点共同决定…...

在 Vue 2 中使用 qrcode 库生成二维码

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…...

在 Ubuntu 系统中,挂起(Suspend)和休眠(Hibernate)

在 Ubuntu 系统中&#xff0c;挂起&#xff08;Suspend&#xff09;和休眠&#xff08;Hibernate&#xff09;是两种常见的电源管理模式。以下是相关命令及说明&#xff1a; --- ### **1. 挂起&#xff08;Suspend&#xff09;** 挂起会将当前系统状态保存到内存中&#xff0…...

什么是声明式UI什么是命令式UI?鸿蒙ArkTS为什么是声明式UI-优雅草卓伊凡

什么是声明式UI什么是命令式UI&#xff1f;鸿蒙ArkTS为什么是声明式UI-优雅草卓伊凡 一、UI编程范式的根本分野 在软件开发领域&#xff0c;用户界面(UI)构建方式经历了三次重大范式转换。作为优雅草科技CTO&#xff0c;卓伊凡在多个操作系统开发实践中发现&#xff0c;UI框架…...

nRF Connect SDK system off模式介绍

目录 概述 1. 软硬件环境 1.1 软件开发环境 1.2 硬件环境 2 System Off 模式 2.1 模式介绍 2.2 注意事项 3 功能实现 3.1 框架结构介绍 3.2 代码介绍 4 功能验证 4.1 编译和下载代码 4.2 测试 4.3 使能CONFIG_APP_USE_RETAINED_MEM的测试 5 main.c的源代码文件…...

node.js 实战——餐厅静态主页编写(express+node+ejs+bootstrap)

ejs页面 <!DOCTYPE html> <html> <head><title><% title %></title><link relstylesheet href/stylesheets/style.css/><link relstylesheet href/stylesheets/font-awesome.css/><link relstylesheet href/stylesheets/f…...

晶体布局布线

1Clock时钟电路 时钟电路就是类似像时钟一样准确运动的震荡电路&#xff0c;任何工作都是依照时间顺序&#xff0c;那么产生这个时间的电路就是时钟电路&#xff0c;时钟电路一般是由晶体振荡器、晶振、控制芯片以及匹配电容组成 2.时钟电路布局 晶体电路布局需要优先考虑&…...

数据结构--树

一、树的概念 树是由n(n≥0)个节点组成的有限集合&#xff0c;它满足以下条件&#xff1a; 1. 当n0时&#xff0c;称为空树 2. 当n>0时&#xff0c;有且仅有一个特定的节点称为根节点(root) 3. 其余节点可分为m(m≥0)个互不相交的有限集合&#xff0c;每个集合本身又是一…...

5月7号.

flex布局: 表单标签: 表单标签-表单项:...

Spark 之 YarnCoarseGrainedExecutorBackend

YarnCoarseGrainedExecutorBackend executor ID , 在日志里也有体现。 25/05/06 12:41:58 INFO YarnCoarseGrainedExecutorBackend: Successfully registered with driver 25/05...

Webug4.0靶场通关笔记19- 第24关邮箱轰炸

目录 第24关 邮箱轰炸 1.配置环境 2.打开靶场 3.源码分析 4.邮箱轰炸 &#xff08;1&#xff09;注册界面bp抓包 &#xff08;2&#xff09;发送到intruder &#xff08;3&#xff09;配置position &#xff08;4&#xff09;配置payload &#xff08;5&#xff09;开…...

机器学习实战:6种数据集划分方法详解与代码实现

在机器学习项目中&#xff0c;合理划分数据集是模型开发的关键第一步。本文将全面介绍6种常见数据格式的划分方法&#xff0c;并附完整Python代码示例&#xff0c;帮助初学者掌握这一核心技能。 一、数据集划分基础函数 1. 核心函数&#xff1a;train_test_split from sklea…...

PostgreSQL 查询历史最大进程数方法

PostgreSQL 查询历史最大进程数方法 PostgreSQL 提供了多种方式来查询数据库的历史最大进程数&#xff08;连接数&#xff09;。以下是几种有效的方法&#xff1a; 一、使用统计收集器数据 1. 查看当前统计信息 SELECT max_connections, (SELECT setting FROM pg_settings …...

第十二节:图像处理基础-图像平滑处理 (均值滤波、高斯滤波、中值滤波)

在数字图像处理中&#xff0c;图像平滑&#xff08;Image Smoothing&#xff09;是去除噪声、改善图像质量的关键技术之一。通过滤波算法&#xff0c;可以有效地抑制高频噪声&#xff0c;但同时可能牺牲部分图像细节。本文将以均值滤波、高斯滤波和中值滤波为核心&#xff0c;结…...

Python中的global与nonlocal关键字详解

一、前言 在Python编程中&#xff0c;变量作用域是一个非常重要的概念。对于初学者来说&#xff0c;经常会遇到在函数内部无法修改外部变量的问题。这时候&#xff0c;global和nonlocal关键字就能派上用场了。本文将详细介绍这两个关键字的用法、区别以及适用场景&#xff0c;…...

LVGL-对象 lv_obj_t

LVGL-对象 lv_obj_t **LVGL 对象核心概念总结****1. 对象与控件的关系****2. 对象的基本属性****3. 父子对象结构****4. 屏幕与图层管理****活动屏幕&#xff08;Active Screen&#xff09;****图层&#xff08;Layers&#xff09;** **5. 关键函数与操作****6. 面向对象设计的…...

【C/C++】ARM处理器对齐_伪共享问题

文章目录 1 什么是伪共享&#xff1f;2 为什么对齐&#xff1f;3 伪共享的实际影响4 为什么必须是 64 字节&#xff1f;5 其他替代方案6 验证对齐效果总结 1 什么是伪共享&#xff1f; 伪共享是 多线程编程中的一种性能问题&#xff0c;其本质是&#xff1a; 缓存行&#xff…...