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

[C++]继承

🥁作者: 华丞臧
📕​​​​专栏:【C++】
各位读者老爷如果觉得博主写的不错,请诸位多多支持(点赞+收藏+关注)。如果有错误的地方,欢迎在评论区指出。

推荐一款刷题网站 👉LeetCode


文章目录

  • 一、继承的概念及其定义
    • 1.1 继承的概念
    • 1.2 继承的定义
      • 1.2.1 定义格式
      • 1.2.2 继承关系和访问限定符
      • 1.2.3继承基类成员访问方式的变化
  • 二、基类和派生类对象赋值转换
  • 三、继承中的作用域
  • 四、派生类的默认成员函数
  • 五、继承--友元和静态成员
    • 5.1 继承与友元
    • 5.2 继承与static静态成员
  • 六、复杂的菱形继承及菱形虚拟继承
    • 6.1 单继承和多继承
    • 6.2 菱形继承
    • 6.3 虚拟继承解决数据冗余和二义性的原理
  • 七、继承的总结


一、继承的概念及其定义

1.1 继承的概念

继承机制是面向对象程序设计实现代码复用最重要的手段,继承允许程序员在保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称为派生类,原有类称为基类。派生类也称为子类,基类也称为父类。

继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。以前我们学习接触到的复用都是函数复用,继承是类设计层次的复用
来看下面的例子:

class Person
{
public:void Print(){cout << "name:" << _name << endl;cout << "age:" << _age << endl;}protected:string _name = "peter"; // 姓名int _age = 18;  // 年龄
};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;
}

继承后父类的Person的成员(成员函数+成员变量)都会变成子类的一部分。这里体现出了Student和Teacher复用了Person的成员。
在这里插入图片描述

调用Print函数可以看到函数的复用:
在这里插入图片描述

1.2 继承的定义

1.2.1 定义格式

下面代码中,Student是子类,也称为派生类;Person是父类,也称为基类;其中public表示继承方式。
在这里插入图片描述

1.2.2 继承关系和访问限定符

在这里插入图片描述

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

类成员/继承方式public继承protected继承private继承
基类的public成员派生类的public成员派生类的protected成员派生类的private成员
基类的protected成员派生类的protected成员派生类的protected成员派生类的private成员
基类的private成员在派生类中不可见在派生类中不可见在派生类中不可见
// 实例演示三种继承关系下基类成员的各类型成员访问关系的变化  
class Person
{
public :void Print (){cout<<_name <<endl;}
protected :// public/protected继承在子类中可见,private继承在子类中不可见string _name ; 
private :int _age ; // 在子类中不可见,但是被继承了
};//class Student : protected Person
//class Student : private Person
class Student : public Person
{
protected :int _stunum ; // 学号
};

总结:

  1. 基类private成员在子类中无论什么方式继承都是不可见的。这里的不可见是指基类的私有成员还是被继承到了派生类对象中,但是语法上限制派生类对象不管在类里面还是类外面都不能去访问它。
  2. 基类private成员在派生类中是不能被访问的,如果基类成员不想在类外直接被访问,但需要在派生类中能访问,就定义为protected,可以看出保护成员限定符就是因继承才出现的。
  3. 基类的其他成员在子类的访问方式 == Min(成员在基类的访问限定符,继承方式),public > protected > private。
  4. 使用关键字class的默认继承方式是private,使用struct默认继承方式是public,不过最好显式的写出继承方式。
  5. 在实际运用中一般使用public继承,很少使用protected/private继承,也不提倡使用protetced/private继承,因为protetced/private继承下来的成员都只能在派生类的类里面使用,实际中扩展维护性不强。(继承本就是为了复用,私有代码就不能服用了)

二、基类和派生类对象赋值转换

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

在这里插入图片描述

class Person
{
public:Person(string name = "", int age = 0){_name = name;_age = age;}void Print(){cout << _name << endl;}protected:string _name; // 姓名int _age; // 年龄
};class Student : public Person
{
public:Student(int stunum = 0):Person(){_stunum = stunum;}void Show(){cout << _name << endl;cout << _age << endl;cout << _stunum << endl;}protected:int _stunum; // 学号
};int main()
{Student s;s.Show();Person* per = &s;   //发生切片//Person per = s;//Person& per = s;per->Print();// 3.基类的指针可以通过强制类型转换赋值给派生类的指针per = &s;Student* ps1 = (Student*)per; // 这种情况转换时可以的。per = &pobj;Student* ps2 = (Student*)per; // 这种情况转换时虽然可以,但是会存在越界访问的问题return 0;
}

在这里插入图片描述

三、继承中的作用域

  1. 在继承体系中基类和派生类都有独立的作用域
  2. 子类和父类中有同名成员,子类成员将屏蔽父类对同名成员的直接访问,这种情况称为隐藏,也叫重定义。
  3. 注意:如果是成员函数的隐藏,只需要函数名相同就可以构成隐藏。(在子类成员函数中,可以使用 基类::基类成员 显示访问
  4. 实际中,在继承体系里最好不要定义同名成员。
class Person
{
protected:string _name = "小李子"; // 姓名int _num = 111;   // 身份证号
};class Student : public Person
{
public:void Print(){cout << " 姓名:" << _name << endl;cout << " 身份证号:" << Person::_num << endl;cout << " 学号:" << _num << endl;}
protected:int _num = 999; // 学号
};

Student的_num和Person的_num构成隐藏关系,可以看出这样代码虽然能跑,但是非常容易混淆;子类中必须显示访问才能使用隐藏成员。
在这里插入图片描述
再来看看成员函数的隐藏:

class A
{
public:void fun(){cout << "func()" << endl;}
};class B : public A
{
public:void fun(int i){A::fun();cout << "func(int i)->" << i << endl;}
};void Test()
{B b;b.fun(10);
};

B中的fun和A中的fun不是构成重载,因为不是在同一作用域;B中的fun和A中的fun构成隐藏,成员函数满足函数名相同就构成隐藏
在这里插入图片描述

四、派生类的默认成员函数

6个默认成员函数,“默认”的意思就是指我们不写,编译器会变我们自动生成一个,那么在派生类中,这几个成员函数是如何生成的呢?

  1. 派生类的构造函数必须调用基类的构造函数初始化基类的那一部分成员。如果基类没有默认的构造函数,则必须在派生类构造函数的初始化列表阶段显示调用。
  2. 派生类的拷贝构造函数必须调用基类的拷贝构造完成基类的拷贝初始化。
  3. 派生类的operator=必须要调用基类的operator=完成基类的复制。
  4. 派生类的析构函数会在被调用完成后自动调用基类的析构函数清理基类成员。因为这样才能保证派生类对象先清理派生类成员再清理基类成员的顺序。
  5. 派生类对象初始化先调用基类构造再调派生类构造。
  6. 派生类对象析构清理先调用派生类析构再调基类的析构。
  7. 因为后续一些场景析构函数需要构成重写,重写的条件之一是函数名相同(暂时先了解)。那么编译器会对析构函数名进行特殊处理,处理成destrutor(),所以父类析构函数不加virtual的情况下,子类析构函数和父类析构函数构成隐藏关系。

在这里插入图片描述
在这里插入图片描述
通过上述说明,我们能总结一下几点:

  • 派生类当中的基类部分是使用自己的构造函数初始化,子类调用其默认构造函数,没有默认构造就必须显示调用父类构造;对基类数据的操作一般调用基类的成员函数。
  • 派生类的模型是基类在前,派生类的成员在后,且父类先构造后析构,子类后构造先析构;这是由于栈的特性所决定的,栈是先入后出的。
class Person
{
public:Person(const char* name = "peter"): _name(name){cout << "Person()" << endl;}Person(const Person& p): _name(p._name){cout << "Person(const Person& p)" << endl;}Person& operator=(const Person& p){cout << "Person operator=(const Person& p)" << endl;if (this != &p)_name = p._name;return *this;}~Person(){cout << "~Person()" << endl;}
protected:string _name; // 姓名
};class Student : public Person
{
public:Student(const char* name, int num): Person(name), _num(num){cout << "Student()" << endl;}Student(const Student& s): Person(s), _num(s._num){cout << "Student(const Student& s)" << endl;}Student& operator = (const Student& s){cout << "Student& operator= (const Student& s)" << endl;if (this != &s){Person::operator =(s);_num = s._num;}return *this;}~Student(){cout << _num;cout << ":~Student()" << endl;}protected:int _num; //学号
};
void Test()
{Student s1("jack", 18);Student s2(s1);Student s3("rose", 17);s1 = s3;
}int main()
{Test();return 0;
}

在这里插入图片描述

五、继承–友元和静态成员

5.1 继承与友元

友元关系不能继承,也就是说基类友元不能访问子类私有和保护成员 。

class Student;  //声明,Display函数向上查找Student
class Person
{
public:friend void Display(const Person& p, const Student& s);
protected:string _name; // 姓名
};
class Student : public Person
{
protected:int _stuNum; // 学号
};void Display(const Person& p, const Student& s)
{cout << p._name << endl;cout << s._stuNum << endl;
}
void test()
{Person p;Student s;Display(p, s);
}

程序无法运行成功,Student成员变量_stuNum是保护成员,在基类Person的友元中是无法被访问的。
在这里插入图片描述

5.2 继承与static静态成员

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

六、复杂的菱形继承及菱形虚拟继承

6.1 单继承和多继承

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

前面我们看到的都是单继承,单继承并不是说只有两个类,而是类之间的基础关系是线性的,即一个父亲只有一个儿子,如下图:

在这里插入图片描述

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

在这里插入图片描述

6.2 菱形继承

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

在这里插入图片描述

class Person
{
protected:string _name; // 姓名
};class Student : public Person
{
protected:int _stuNum; // 学号
};class Teacher : public Person
{
protected:int _id; // 职工编号
};class Assistant : public Student, public Teacher{
protected:string _majorCourse;  // 主修课程
};

通过监视窗口观察到,子类对象中存在两份Person数据,如下图:
在这里插入图片描述

在C++中支持多继承,因此就会存在菱形继承;菱形继承就是子类继承的多个父类当中继承了相同的类。这里就存在一个问题:当子类继承的多个父类中继承了相同的类,那么就子类应该继承那一个呢,还是说两个继承。

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

在这里插入图片描述
C++提供了virtual关键字,用来定义虚拟函数和虚继承;虚拟继承可以解决菱形继承的二义性和数据冗余问题。如上面的继承关系,在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 Assistant : public Student, public Teacher
{
protected:string _majorCourse; // 主修课程
};

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

为了研究虚拟继承原理,我们给出了一个简化的菱形继承继承体系,再借助内存窗口观察对象成员的模型。

class A
{
public:int _a;
};class B : public A
// class B : virtual public A
{
public:int _b;
};class C : public A// class C : virtual public A
{
public:int _c;
};class D : public B, public C
{
public:int _d;
};int main()
{D d;d.B::_a = 1;d.C::_a = 2;d._b = 3;d._c = 4;d._d = 5;return 0;
}

下图是菱形继承的内存对象成员模型,可以看到数据冗余:
在这里插入图片描述

下图是菱形虚拟继承的内存对象成员模型:这里可以分析出D对象中将A放到的了对象组成的最下面,这个A同时属于B和C,那么B和C如何去找到公共的A呢?这里是通过了B和C的两个指针,指向的一张表。这两个指针叫虚基表指针,这两个表叫虚基表。虚基表中存的偏移量。通过偏移量可以找到下面的A。
在这里插入图片描述

B和C通过对象中的虚基表指针找到偏移量,再通过偏移量找到A。
在这里插入图片描述

下面是上面的Person关系菱形虚拟继承的原理解释:
在这里插入图片描述

七、继承的总结

  1. C++语法复杂,多继承就是一个体现。有了多继承,就存在菱形继承,有了菱形继承就有菱形虚拟继承,底层实现就很复杂。所以一般不建议设计出多继承,一定不要设计出菱形继承,否则在复杂度及性能上都有问题。

  2. 继承和组合

    • public继承是一种is-a的关系。也就是说每个派生类对象都是一个基类对象。
    • 组合是一种has-a的关系。假设B组合了A,每个B对象中都有一个A对象。
    • 继承允许你根据基类的实现来定义派生类的实现。这种通过生成派生类的复用通常被称为白箱复用(white-box reuse)。术语“白箱”是相对可视性而言:在继承方式中,基类的内部细节对子类可见 。继承一定程度破坏了基类的封装,基类的改变,对派生类有很大的影响。派生类和基类间的依赖关系很强,耦合度高。
    • 对象组合是类继承之外的另一种复用选择。新的更复杂的功能可以通过组装或组合对象来获得。对象组合要求被组合的对象具有良好定义的接口。这种复用风格被称为黑箱复用(black-box reuse),因为对象的内部细节是不可见的。对象只以“黑箱”的形式出现。组合类之间没有很强的依赖关系,耦合度低。优先使用对象组合有助于你保持每个类被封装。
    • 实际尽量多去用组合。组合的耦合度低,代码维护性好。不过继承也有用武之地的,有些关系就适合继承那就用继承,另外要实现多态,也必须要继承。类之间的关系可以用继承,可以用组合,就用组合。
// Car和BMW Car和Benz构成is-a的关系
class Car
{
protected:string _colour = "白色"; // 颜色string _num = "陕ABIT00"; // 车牌号
};class BMW : public Car
{
public:void Drive() {cout << "好开-操控" << endl;}
};class Benz : public Car
{
public:void Drive() {cout << "好坐-舒适" << endl;}
};// Tire和Car构成has-a的关系class Tire
{
protected:string _brand = "Michelin";  // 品牌size_t _size = 17;         // 尺寸};class Car
{
protected:string _colour = "白色"; // 颜色string _num = "陕ABIT00"; // 车牌号Tire _t; // 轮胎
}; 

相关文章:

[C++]继承

&#x1f941;作者&#xff1a; 华丞臧 &#x1f4d5;​​​​专栏&#xff1a;【C】 各位读者老爷如果觉得博主写的不错&#xff0c;请诸位多多支持(点赞收藏关注)。如果有错误的地方&#xff0c;欢迎在评论区指出。 推荐一款刷题网站 &#x1f449;LeetCode 文章目录一、继承…...

优化知识管理方法丨整理零碎信息,提高数据价值

信息流时代&#xff0c;知识成集合倍数增长&#xff0c;看似我们学习了很多知识&#xff0c;但知识零碎无系统&#xff0c;知识之间缺乏联系&#xff0c;没有深度&#xff0c;所以虽然你很努力&#xff0c;但你发现自己的能力增长特别缓慢&#xff0c;你需要整理知识将零散的知…...

Windows操作系统的体系结构、运行环境和运行状态

我是荔园微风&#xff0c;作为一名在IT界整整25年的老兵&#xff0c;今天我们来重新审视一下Windows这个我们熟悉的不能再熟悉的系统。说Windows操作系统的运行环境和运行状态&#xff0c;首先要介绍一下Windows操作系统的体系结构&#xff0c;然后再要说到最重要的两个概念:核…...

【工作笔记】Http响应头过长

起因 突然有测试小伙伴反馈进公司官网主页会白屏&#xff0c;但只是个例不是普遍现象 查监控发现没监控到异常问题 查了很久&#xff08;这个很久单指对于线上问题来说&#xff09;才定位是请求的异常&#xff0c;因为这套系统的异常用的是 ExceptionHandler&#xff0c;这也导…...

hive建分区表,分桶表,内部表,外部表

hive建分区表&#xff0c;分桶表&#xff0c;内部表&#xff0c;外部表 一、概念介绍 Hive是基于Hadoop的一个工具&#xff0c;用来帮助不熟悉 MapReduce的人使用SQL对存储在Hadoop中的大规模数据进行数据提取、转化、加载。Hive数据仓库工具能将结构化的数据文件映射为一张数…...

【分享】灌溉制度设计小程序VB源代码

说明 根据作物需水特性和当地气候、土壤、农业技术及灌水技术等因素制定的灌水方案。主要内容包括灌水次数、灌水时间、灌水定额和灌溉定额。灌溉制度是规划、设计灌溉工程和进行灌区运行管理的基本资料&#xff0c;是编制和执行灌区用水计划的重要依据。 1—计划湿润土层允…...

PR9268/300-000库存现货振动传感器 雄霸工控

PR9268/300-000库存现货振动传感器 雄霸工控PR9268/300-000库存现货振动传感器 雄霸工控SDM010PR9670/110-100PR9670/010-100PR9670/003-000PR9670/002-000PR9670/001-000PR9670/000-000PR9600/014-000PR9600/011-000PR9376/010-021PR9376/010-011PR9376/010-011PR9376/010-001…...

浅谈模型评估选择及重要性

作者&#xff1a;王同学 来源&#xff1a;投稿 编辑&#xff1a;学姐 模型评估作为机器学习领域一项不可分割的部分&#xff0c;却常常被大家忽略&#xff0c;其实在机器学习领域中重要的不仅仅是模型结构和参数量&#xff0c;对模型的评估也是至关重要的&#xff0c;只有选择那…...

多线程的初识和创建

✨个人主页&#xff1a;bit me&#x1f447; ✨当前专栏&#xff1a;Java EE初阶&#x1f447; ✨每日一语&#xff1a;知不足而奋进&#xff0c;望远山而前行。 目 录&#x1f4a4;一. 认识线程&#xff08;Thread&#xff09;&#x1f34e;1. 线程的引入&#x1f34f;2. 线程…...

一句话设计模式3:工厂模式

工厂模式:new多种对象的简单方式。 文章目录 工厂模式:new多种对象的简单方式。前言一、两种工厂模式二、如何实现工厂模式1. 简单工厂2. 抽象工厂总结前言 工厂模式可以说比较常见的设计模式,仔细观察在很多源码中都有此种模式的应用;用来解决创建对象的创建问题; 一、两种工…...

【Codeforces Round #853 (Div. 2)】C. Serval and Toxel‘s Arrays【题解】

题目 Toxel likes arrays. Before traveling to the Paldea region, Serval gave him an array aaa as a gift. This array has nnn pairwise distinct elements. In order to get more arrays, Toxel performed mmm operations with the initial array. In the iii-th opera…...

100天精通Python(数据可视化篇)——第77天:数据可视化入门基础大全(万字总结+含常用图表动图展示)

文章目录1. 什么是数据可视化&#xff1f;2. 为什么会用数据可视化&#xff1f;3. 数据可视化的好处&#xff1f;4. 如何使用数据可视化&#xff1f;5. Python数据可视化常用工具1&#xff09;Matplotlib绘图2&#xff09;Seaborn绘图3&#xff09;Bokeh绘图6. 常用图表介绍及其…...

PMP考前冲刺2.27 | 2023新征程,一举拿证

题目1-2&#xff1a;1.在产品开发过程中&#xff0c;项目发起人向项目团队推荐了一种新材料&#xff0c;新材料比现有的材料更便宜而且性能更好。如果团队采用新材料&#xff0c;不但有利于提升产品质量&#xff0c;而且可以显著降低成本。项目经理应该怎么办?A.采用新材料&am…...

【C++】map和set的封装(红黑树)

map和set的封装一、介绍二、stl源码剖析三、仿函数获取数值四、红黑树的迭代器五、map的[]5.1 普通迭代器转const迭代器六、set源码七、map源码八、红黑树源码一、介绍 首先要知道map和set的底层都是用红黑树实现的 【数据结构】红黑树 set只需要一个key&#xff0c;但是map既…...

【批处理脚本】-1.14-移动文件(夹)命令move

"><--点击返回「批处理BAT从入门到精通」总目录--> 共10页精讲(列举了所有move的用法,图文并茂,通俗易懂) 在从事“嵌入式软件开发”和“Autosar工具开发软件”过程中,经常会在其集成开发环境IDE(CodeWarrior,S32K DS,Davinci,EB Tresos,ETAS…)中,…...

逻辑地址和物理地址转换

在操作系统的学习中&#xff0c;很多抵挡都会涉及虚拟地址转换为物理地址的计算&#xff0c;本篇就简单介绍一下在分页存储管理、分段存储管理、磁盘存储管理中涉及的地址转换问题。 虚拟地址与物理地址 编程一般只有可能和逻辑地址打交道&#xff0c;比如在 C 语言中&#x…...

HyperGBM用4记组合拳提升AutoML模型泛化能力

本文作者&#xff1a;杨健&#xff0c;九章云极 DataCanvas 主任架构师 如何有效提高模型的泛化能力&#xff0c;始终是机器学习领域的重要课题。经过大量的实践证明比较有效的方式包括&#xff1a; 利用Early Stopping防止过拟合通过正则化降低模型的复杂度使用更多的训练数…...

P6软件中的前锋线设置

卷首语 所谓前锋线&#xff0c;是指从评估时刻的时标点出发&#xff0c;用点划线一次连接各项活动的实际进展位置所形成的的线段&#xff0c;其通常为折线。 关键路径法 前锋线比较法&#xff0c;是通过在进度计划中绘制实际进度前锋线以判断活动实际进度与计划进度的偏差&a…...

Spring Boot + Vue3 前后端分离 实战 wiki 知识库系统<二>---后端架构完善与接口开发

数据库准备&#xff1a; 在上一次Spring Boot Vue3 前后端分离 实战 wiki 知识库系统<一>---Spring Boot项目搭建已经将SpringBoot相关的配置环境给搭建好了&#xff0c;接下来则需要为咱们的项目创建一个数据库。 1、mysql的安装&#xff1a; 关于mysql的安装这里就…...

如何在logback.xml中自定义动态属性

原文地址&#xff1a;http://blog.jboost.cn/trick-logback-prop.html 当使用logback来记录Web应用的日志时&#xff0c;我们通过在logback.xml中配置appender来指定日志输出格式及输出文件路径&#xff0c;这在一台主机或一个文件系统上部署单个实例没有问题&#xff0c;但是…...

嵌入式系统硬件设计与实践(第一步下载eda软件)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 现实生活中&#xff0c;我们经常发现有的人定了很多的目标&#xff0c;但是到最后一个都没有实现。这听上去有点奇怪&#xff0c;但确实是实实在在…...

Portraiture4免费磨皮插件支持PS/LR

Portraiture 4免去了繁琐的手工劳动&#xff0c;选择性的屏蔽和由像素的平滑&#xff0c;以帮助您实现卓越的肖像润色。智能平滑&#xff0c;并删除不完善之处&#xff0c;同时保持皮肤的纹理和其他重要肖像的细节&#xff0c;如头发&#xff0c;眉毛&#xff0c;睫毛等。 一键…...

Python学习笔记202302

1、numpy.empty 作用&#xff1a;根据给定的维度和数值类型返回一个新的数组&#xff0c;其元素不进行初始化。 用法&#xff1a;numpy.empty(shape, dtypefloat, order‘C’) 2、logging.debug 作用&#xff1a;Python 的日志记录工具&#xff0c;这个模块为应用与库实现了灵…...

2023年大数据面试开胃菜

1、kafka的message包括哪些信息一个Kafka的Message由一个固定长度的header和一个变长的消息体body组成&#xff0c;header部分由一个字节的magic(文件格式)和四个字节的CRC32(用于判断body消息体是否正常)构成。当magic的值为1的时候&#xff0c;会在magic和crc32之间多一个字节…...

优雅的controller层设计

controller层设计 Controller 层逻辑 ​ MVC架构下&#xff0c;我们的web工程结构会分为三层&#xff0c;自下而上是dao层&#xff0c;service层和controller层。controller层为控制层&#xff0c;主要处理外部请求。调用service层&#xff0c;一般情况下&#xff0c;contro…...

同步、通信、死锁

基础概念竞争资源引起两个问题死锁&#xff1a;因资源竞争陷入永远等待的状态饥饿&#xff1a;一个可运行程序由于其他进程总是优先于它&#xff0c;而被调用程序总是无限期地拖延而不能执行进程互斥&#xff1a;若干进程因相互争夺独占型资源而产生的竞争关系进程同步&#xf…...

【聚类】谱聚类解读、代码示例

【聚类】谱聚类详解、代码示例 文章目录【聚类】谱聚类详解、代码示例1. 介绍2. 方法解读2.1 先验知识2.1.1 无向权重图2.1.2 拉普拉斯矩阵2.2 构建图&#xff08;第一步&#xff09;2.2.1 ϵ\epsilonϵ 邻近法2.2.2 k 近邻法2.2.3 全连接法2.3 切图&#xff08;第二步&#xf…...

最牛逼的垃圾回收期ZGC(1),简介

1丶什么是ZGC? ZGC是JDK 11中引入的一种可扩展的、低延迟的垃圾收集器。ZGC最主要的特点是&#xff1a;在非常短的时间内&#xff08;一般不到10ms&#xff09;&#xff0c;就可以完成一次垃圾回收&#xff0c;而且这个时间是与堆的大小无关的。另外&#xff0c;ZGC支持非常大…...

微服务的Feign到底是什么

Feign是什么 分区是一种数据库优化技术&#xff0c;它可以将大表按照一定的规则分成多个小表&#xff0c;从而提高查询和维护的效率。在分区的过程中&#xff0c;数据库会将数据按照分区规则分配到不同的分区中&#xff0c;并且可以在分区中使用索引和其他优化技术来提高查询效…...

JavaScript 正则表达式

正则表达式&#xff08;英语&#xff1a;Regular Expression&#xff0c;在代码中常简写为regex、regexp或RE&#xff09;使用单个字符串来描述、匹配一系列符合某个句法规则的字符串搜索模式。搜索模式可用于文本搜索和文本替换。什么是正则表达式&#xff1f;正则表达式是由一…...

wordpress 重复点赞/专业整站优化

经过两个小时的奋战&#xff0c;终于将博客园服务器抢救过来。问题的原因已经找到。等会我会写文章描述这次抢救过程。 这两天博客园服务器的不稳定&#xff0c;给大家带来了很大的麻烦&#xff0c;在这里博客园向大家表示深深的歉意!希望得到你的谅解!...

苏州新区网站制作/seo和sem的关系

### MVC![](http://p0zfk1qh0.bkt.clouddn.com/markdownmvc.png) 视图&#xff08;View&#xff09;&#xff1a;用户界面。 控制器&#xff08;Controller&#xff09;&#xff1a;业务逻辑 模型&#xff08;Model&#xff09;&#xff1a;数据保存 ** View 传送指令到 Contro…...

百度快照 直接进网站/google移动服务应用优化

监控系统进程资源的使用情况是IT运维的常规操作。在实际工作中&#xff0c;运维人员有可能遇到可以使用Zabbix Agent监控linux系统进程&#xff0c;却无法监控windows系统进程的情况。这是因为Zabbix Agent可以通过linux系统内置键值进行监控进程&#xff0c;而windows平台则不…...

记事本做网站/专门看网站的浏览器

题图摄于北京奥利匹克公园注&#xff1a;微信公众号不按照时间排序&#xff0c;请关注公众号“亨利笔记”&#xff0c;并加星标以置顶&#xff0c;以免错过更新。本文作者为VMware研发工程师&#xff0c;KubeFATE开源项目维护者。KubeFATE 日志聚合从 KubeFATE v1.5.1开始支持对…...

邯郸小程序定制开发/公司网站seo外包

插入排序,就是将数组中的一个个元素插入到已经排好序的数组中. 代码实现: public static void insertSort2(int[] arr){//从第二个元素开始,往前依次比较相邻的两个元素,如果后面的比前面的元素大,则直接终止此次循环.这样可以节省比较次数.for (int i 1; i < arr.length; …...

建昌县城乡规划建设局网站/怎么弄自己的网站

使用XML在SQL Server上创建计算列 在SQL Server数据库中&#xff0c;当你想使用一个数据&#xff0c;而这个数据不保存在表中&#xff0c;计算列很有用。例如&#xff0c;你有一张表&#xff0c;它包括列dollar amounts, wholesale prices和retail prices。你肯定不想在每次查询…...