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

【C++】类和对象三大特性--继承

文章目录

  • 1.继承的概念及定义
    • 1.1继承的概念
    • 1.2 继承定义
      • 1.2.1定义格式
      • 1.2.2继承关系和访问限定符
      • 1.2.3继承基类成员访问方式的变化
  • 2.基类和派生类对象赋值转换
  • 3.继承中的作用域
  • 4.派生类的默认成员函数
  • 5.继承与友元
  • 6. 继承与静态成员
  • 7.复杂的菱形继承及菱形虚拟继承
    • 虚拟继承解决数据冗余和二义性的原理
  • 8.继承的总结和反思


1.继承的概念及定义

1.1继承的概念

继承是面向对象三大特性之一

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

有些类与类之间存在特殊的关系,例如下图中:

image-20230206143107865

我们发现,定义这些类时,下级别的成员除了拥有上一级的共性,还有自己的特性。

这个时候我们就可以考虑利用继承的技术,减少重复代码


1.2 继承定义

1.2.1定义格式

继承的语法:class 子类 : 继承方式 父类

下面我们看到Person是父类,也称作基类。Student是子类,也称作派生类

class Person
{
public:void Print(){cout << "name:" << _name << endl;cout << "age:" << _age << endl;}
protected:string _name = "peter"; // 姓名int _age = 18; // 年龄
};
// 继承后父类的Person的成员(成员函数+成员变量)都会变成子类的一部分。这里体现出了
//Student复用了Person的成员。下面我们使用监视窗口查看Student,可
//以看到变量的复用。调用Print可以看到成员函数的复用。
class Student : public Person
{
protected:int _stuid; // 学号
};

image-20230206143533135


1.2.2继承关系和访问限定符

继承方式一共有三种:

  • 公共继承
  • 保护继承
  • 私有继承

image-20230206144023718


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

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

image-20230206143807326

总结:

  1. 基类private成员在派生类中无论以什么方式继承都是不可见的。这里的不可见是指基类的私
    有成员还是被继承到了派生类对象中,但是语法上限制派生类对象不管在类里面还是类外面
    都不能去访问它。

  2. 基类private成员在派生类中是不能被访问,如果基类成员不想在类外直接被访问,但需要在
    派生类中能访问,就定义为protected。可以看出保护成员限定符是因继承才出现的。

  3. 实际上面的表格我们进行一下总结会发现,基类的私有成员在子类都是不可见。基类的其他
    成员在子类的访问方式 == Min(成员在基类的访问限定符,继承方式),public > protected
    > private。

  4. 使用关键字class时默认的继承方式是private,使用struct时默认的继承方式是public,不过
    最好显示的写出继承方式。

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

//实例演示三种继承关系下基类成员的各类型成员访问关系的变化
class Base1
{
public: int m_A;
protected:int m_B;
private:int m_C;
};//公共继承
class Son1 :public Base1
{
public:void func(){m_A; //可访问 public权限m_B; //可访问 protected权限//m_C; //不可访问}
};void myClass()
{Son1 s1;s1.m_A; //其他类只能访问到公共权限
}//保护继承
class Base2
{
public:int m_A;
protected:int m_B;
private:int m_C;
};
class Son2:protected Base2
{
public:void func(){m_A; //可访问 protected权限m_B; //可访问 protected权限//m_C; //不可访问}
};
void myClass2()
{Son2 s;//s.m_A; //不可访问
}//私有继承
class Base3
{
public:int m_A;
protected:int m_B;
private:int m_C;
};
class Son3:private Base3
{
public:void func(){m_A; //可访问 private权限m_B; //可访问 private权限//m_C; //不可访问}
};
class GrandSon3 :public Son3
{
public:void func(){//Son3是私有继承,所以继承Son3的属性在GrandSon3中都无法访问到//m_A;//m_B;//m_C;}
};

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

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

  • 基类对象不能赋值给派生类对象。

  • 基类的指针或者引用可以通过强制类型转换赋值给派生类的指针或者引用。但是必须是基类
    的指针是指向派生类对象时才是安全的。这里基类如果是多态类型,可以使用RTTI(RunTime Type Information)的dynamic_cast 来进行识别后进行安全转换。(ps:后面多态的内容,这里先了解一下)

image-20230206144938765

class Person
{
protected:string _name; // 姓名string _sex; // 性别int _age; // 年龄
};
class Student : public Person
{
public:int _No; // 学号
};
void Test()
{Student sobj;// 1.子类对象可以赋值给父类对象/指针/引用Person pobj = sobj;Person* pp = &sobj;Person& rp = sobj;//2.基类对象不能赋值给派生类对象sobj = pobj;// 3.基类的指针可以通过强制类型转换赋值给派生类的指针pp = &sobj;Student* ps1 = (Student*)pp; // 这种情况转换时可以的。ps1->_No = 10;pp = &pobj;Student* ps2 = (Student*)pp; // 这种情况转换时虽然可以,但是会存在越界访问的问题ps2->_No = 10;
}

3.继承中的作用域

  1. 在继承体系中基类派生类都有独立的作用域

  2. 子类和父类中有同名成员,子类成员将屏蔽父类对同名成员的直接访问,这种情况叫隐藏
    也叫重定义。(在子类成员函数中,可以使用 基类::基类成员 显示访问

  3. 需要注意的是如果是成员函数的隐藏,只需要函数名相同就构成隐藏。

  4. 注意在实际中在继承体系里面最好不要定义同名的成员

示例1

// Student的_num和Person的_num构成隐藏关系,可以看出这样代码虽然能跑,但是非常容易混淆
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; // 学号
};
void Test()
{Student s1;s1.Print();
};int main()
{Test();return 0;
}

image-20230206145540709

示例2

// B中的fun和A中的fun不是构成重载,因为不是在同一作用域
// B中的fun和A中的fun构成隐藏,成员函数满足函数名相同就构成隐藏。
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;}
};int main()
{B b;b.fun(10);return 0;
}

image-20230206145841961

总结:

  • 访问子类同名成员 直接访问即可
  • 访问父类同名成员 需要加作用域
  1. 子类对象可以直接访问到子类中同名成员
  2. 子类对象加作用域可以访问到父类同名成员
  3. 当子类与父类拥有同名的成员函数,子类会隐藏父类中同名成员函数,加作用域可以访问到父类中同名函数

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

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

  1. 派生类的构造函数必须调用基类的构造函数初始化基类的那一部分成员。如果基类没有默认
    的构造函数,则必须在派生类构造函数的初始化列表阶段显示调用。

  2. 派生类的拷贝构造函数必须调用基类的拷贝构造完成基类的拷贝初始化。

  3. 派生类的operator=必须要调用基类的operator=完成基类的复制。

  4. 派生类的析构函数会在被调用完成后自动调用基类的析构函数清理基类成员。因为这样才能
    保证派生类对象先清理派生类成员再清理基类成员的顺序。

  5. 派生类对象初始化先调用基类构造再调派生类构造。

  6. 派生类对象析构清理先调用派生类析构再调基类的析构。

  7. 因为后续一些场景析构函数需要构成重写,重写的条件之一是函数名相同(这个我们后面会讲
    解)。那么编译器会对析构函数名进行特殊处理,处理成destrutor(),所以父类析构函数不加
    virtual的情况下,子类析构函数和父类析构函数构成隐藏关系

image-20230206150130899

image-20230206151035324

示例

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 << "~Student()" << endl;}
protected:int _num; //学号
};
int main()
{Student s1("jack", 18);Student s2(s1);Student s3("rose", 17);s1 = s3;return 0;
}

image-20230206151542675


5.继承与友元

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

示例

class 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 main()
{Person p;Student s;Display(p, s);
}

报错信息:

image-20230206152009755


6. 继承与静态成员

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

问题:继承中同名的静态成员在子类对象上如何进行访问?

静态成员和非静态成员出现同名,处理方式一致

  • 访问子类同名成员 直接访问即可
  • 访问父类同名成员 需要加作用域

示例:

class Base {
public:static void func(){cout << "Base - static void func()" << endl;}static void func(int a){cout << "Base - static void func(int a)" << endl;}static int m_A;
};int Base::m_A = 100;class Son : public Base {
public:static void func(){cout << "Son - static void func()" << endl;}static int m_A;
};int Son::m_A = 200;//同名成员属性
void test01()
{//通过对象访问cout << "通过对象访问: " << endl;Son s;cout << "Son  下 m_A = " << s.m_A << endl;cout << "Base 下 m_A = " << s.Base::m_A << endl;//通过类名访问cout << "通过类名访问: " << endl;cout << "Son  下 m_A = " << Son::m_A << endl;cout << "Base 下 m_A = " << Son::Base::m_A << endl;
}//同名成员函数
void test02()
{//通过对象访问cout << "通过对象访问: " << endl;Son s;s.func();s.Base::func();cout << "通过类名访问: " << endl;Son::func();Son::Base::func();//出现同名,子类会隐藏掉父类中所有同名成员函数,需要加作作用域访问Son::Base::func(100);
}
int main() {test01();test02();return 0;
}
image-20230206152432121

总结:同名静态成员处理方式和非静态处理方式一样,只不过有两种访问的方式(通过对象 和 通过类名)


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

C++允许一个类继承多个类

语法: class 子类 :继承方式 父类1 , 继承方式 父类2...

多继承可能会引发父类中有同名成员出现,需要加作用域区分

C++实际开发中不建议用多继承

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

image-20230206153043566

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

image-20230206152732421

菱形继承概念:

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

​ 两个派生类继承同一个基类

​ 又有某个类同时继承者两个派生类

​ 这种继承被称为菱形继承,或者钻石继承

image-20230206153101752

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

image-20230206153909780

示例1

class Person
{
public:string _name; // 姓名
};
class Student : public Person
{
protected:int _num; //学号
};
class Teacher : public Person
{
protected:int _id; // 职工编号
};
class Assistant : public Student, public Teacher
{
protected:string _majorCourse; // 主修课程
};
void Test()
{// 这样会有二义性无法明确知道访问的是哪一个Assistant 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 Assistant : public Student, public Teacher
{
protected:string _majorCourse; // 主修课程
};
void Test()
{Assistant a;a._name = "peter";
}

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

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

示例1-没有加virtual关键字

class A
{
public:int _a;
};
class B : public A
{
public:int _b;
};
class C : 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;
}

下图是菱形继承的内存对象成员模型:这里可以看到数据冗余

image-20230206202955591

示例2-加virtual关键字的虚拟继承

class A
{
public:int _a;
};class B : virtual public A
{
public:int _b;
};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;d._a = 6;return 0;
}

下图是菱形虚拟继承的内存对象成员模型:这里可以分析出D对象中将A放到的了对象组成的最下
面,这个A同时属于B和C,那么B和C如何去找到公共的A呢?

这里是通过了B和C的两个指针,指向的一张表。这两个指针叫虚基表指针,这两个表叫虚基表。

虚基表中存的偏移量。通过偏移量可以找到下面的A

image-20230206204005867

我们可能会有疑问为什么D中B和C部分要去找属于自己的A?那么大家看看当下面的赋值发生时,d是
不是要去找出B/C成员中的A才能赋值过去?

D d;
B b = d;
C c = d;

下面是上面的Person关系菱形虚拟继承的原理解释

image-20230206204732195


8.继承的总结和反思

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

  2. 多继承可以认为是C++的缺陷之一,很多后来的语言都没有多继承,如Java。

  3. 继承和组合

    • public继承是一种is-a的关系(如学生是人)。也就是说每个派生类对象都是一个基类对象。
      组合是一种has-a的关系(如眼睛和头的关系)。假设B组合了A,每个B对象中都有一个A对象。

    • 优先使用对象组合,而不是类继承 。

    • 继承允许你根据基类的实现来定义派生类的实现。这种通过生成派生类的复用通常被称
      为白箱复用(white-box reuse)。术语“白箱”是相对可视性而言:在继承方式中,基类的
      内部细节对子类可见 。继承一定程度破坏了基类的封装,基类的改变,对派生类有很
      大的影响。派生类和基类间的依赖关系很强,耦合度高。

    • 对象组合是类继承之外的另一种复用选择。新的更复杂的功能可以通过组装或组合对象
      来获得。对象组合要求被组合的对象具有良好定义的接口。这种复用风格被称为黑箱复
      用(black-box reuse),因为对象的内部细节是不可见的。对象只以“黑箱”的形式出现。
      组合类之间没有很强的依赖关系,耦合度低。优先使用对象组合有助于你保持每个类被
      封装。

    • 实际尽量多去用组合。组合的耦合度低,代码维护性好。不过继承也有用武之地的,有
      些关系就适合继承那就用继承,另外要实现多态,也必须要继承。类之间的关系可以用
      继承,可以用组合,就用组合。


相关文章:

【C++】类和对象三大特性--继承

文章目录1.继承的概念及定义1.1继承的概念1.2 继承定义1.2.1定义格式1.2.2继承关系和访问限定符1.2.3继承基类成员访问方式的变化2.基类和派生类对象赋值转换3.继承中的作用域4.派生类的默认成员函数5.继承与友元6. 继承与静态成员7.复杂的菱形继承及菱形虚拟继承虚拟继承解决数…...

MySQL的存储引擎

目录 一.概念 二.分类 操作 修改默认存储引擎 一.概念 数据库存储引擎是数据库底层软件组织&#xff0c;数据库管理系统&#xff08;DBMS&#xff09;使用数据引擎进行创建、查询、更新和删除数据。不同的存储引擎提供不同的存储机制、索引技巧、锁定水平等功能。现在许多不…...

工程项目管理系统源码-简洁+好用+全面-工程项目管理系统

​ ​工程项目管理系统是指从事工程项目管理的企业&#xff08;以下简称工程项目管理企业&#xff09;受业主委托&#xff0c;按照合同约定&#xff0c;代表业主对工程项目的组织实施进行全过程或若干阶段的管理和服务。 ​系统定义 工程项目管理企业不直接与该工程项目的总承…...

什么是STAR原则?

文章目录&#x1f4cb;前言&#x1f525;省流版&#x1f3af;什么是STAR原则&#x1f3af;进行过程&#x1f4cb;前言 对于大部分还在学习阶段的学生们来说&#xff0c;可能并不了解这个原则的含义&#xff0c;这里的star并不是指英文单词星星。这个原则我也是前段时间才认识到…...

前置知识-初值问题、显式隐式龙格库塔方法、Butcher阵列

1.1.4 龙格一库塔法 将向前欧拉法写成式 (1-37) 的形式, 可以看出它实际上利用了 f ( x , u ) f(x, u) f(x,u) 在 x n...

PythonWeb Django PostgreSQL创建Web项目(二)

安装数据库PostgreSQL并创建数据库 我第一次尝试使用PostgreSQL数据库&#xff0c;why&#xff1f;我喜欢它提供的丰富的数据类型&#xff0c;例如货币类型、枚举类型、几何类型(点、直线、线段、矩形等等)、网络地址类型、文本搜索类型、XML类型JSON类型等等&#xff0c;非常…...

Python学习笔记:使用字符串

使用字符串 使用字符串格式&#xff1a;精简版 百分号 % # 指定要设置其格式的值时&#xff0c;可使用单个值&#xff08;如字符串或数字&#xff09;&#xff0c;可使用元组&#xff08;如果要设置多个值得格式&#xff09;&#xff0c;还可使用字典 >>> format …...

echarts饼图封装

1. 组件 <template> <div :id"id" class"main" :style"{ width: width, height: height }" :ref"id" ></div> </template> <script> import * as echarts from "echarts"; export default { …...

Web3.0 教学基础一

目录 什么是web3.0 Web 1.0 概念 Web 2.0 概念 Web 3.0 概念 Web 3.0 的优势 什么是DAPP 什么是web3.0 在了解web3.0之前我们需要了解下前面的web1.0与web2.0。 Web 1.0 概念 Web1.0是万维网最初的版本&#xff0c;而静态网站则被认为是全网Web 1.0的起源&#xff0c;用…...

body使用渐变色无效的原因之一:html没有设置高度

直接在css文件中对body设置渐变色&#xff1a; body {height: 100%;background: -webkit-linear-gradient(120deg, #a1c4fd 0%, #c2e9fb 100%);background: -moz-linear-gradient(120deg, #a1c4fd 0%, #c2e9fb 100%);background: -o-linear-gradient(120deg, #a1c4fd 0%, #c2e…...

Python3 函数实例及演示

函数是组织好的&#xff0c;可重复使用的&#xff0c;用来实现单一&#xff0c;或相关联功能的代码段。 函数能提高应用的模块性&#xff0c;和代码的重复利用率。我们已经知道Python提供了许多内建函数&#xff0c;比如print()。但也可以自己创建函数&#xff0c;这被叫做用户…...

HTB打靶(Active Directory 101 Multimaster)

Nmap扫描 Starting Nmap 7.93 ( https://nmap.org ) at 2023-02-08 02:52 EST Stats: 0:00:51 elapsed; 0 hosts completed (1 up), 1 undergoing SYN Stealth Scan SYN Stealth Scan Timing: About 55.85% done; ETC: 02:54 (0:00:40 remaining) Nmap scan report for 10.129…...

漏洞预警|Apache Sling JCR Base 存在JNDI注入漏洞

棱镜七彩安全预警 近日网上有关于开源项目Apache Sling JCR Base 存在JNDI注入漏洞&#xff0c;棱镜七彩威胁情报团队第一时间探测到&#xff0c;经分析研判&#xff0c;向全社会发起开源漏洞预警公告&#xff0c;提醒相关安全团队及时响应。 项目介绍 Apache Sling是一个基于…...

【学习笔记】DFA的构造

虽然平时做过但是考场上肯定还是不会&#xff0c;不过没事干还是写一下吧 Myhill-Nerode\text{Myhill-Nerode}Myhill-Nerode 定理&#xff1a;给定一个语言LLL&#xff0c;定义在字符串上一个关系为&#xff0c;若对于所有的zzz&#xff0c;xzxzxz在LLL中当且仅当yzyzyz在LLL中…...

MyBatis 之二(增、删、改操作)

文章目录1. 修改操作1.1 在 mapper&#xff08;interface&#xff09;里面添加修改方法的声明1.2 在 XMl 中添加 <update> 标签和修改的 sql 代码1.3 在 UserMapper 中右键 Generate 点击 Test 生成 update 测试类2. 删除操作2.1 在 mapper &#xff08;interface&#x…...

28k入职腾讯测试岗那天,我哭了,这5个月付出的一切总算没有白费~

先说一下自己的个人情况&#xff0c;计算机专业&#xff0c;16年普通二本学校毕业&#xff0c;经历过一些失败的工作经历后&#xff0c;经推荐就进入了华为的测试岗&#xff0c;进去才知道是接了个外包项目&#xff0c;不太稳定的样子&#xff0c;可是刚毕业谁知道什么外包不外…...

【surfaceflinger源码分析】surfaceflinger进程的消息驱动模型

概述 对于surfaceflinger大多数人都知道它的功能是做图形合成的&#xff0c;用英语表示就是指composite。其大致框图如下: 各个Android app将自己的图形画面通过surface为载体通过AIDL接口(Binder IPC)传递到surfaceflinger进程surfaceflinger进程中的composition engine与HW…...

「架构师」001计算机组成与体系结构

文章目录 前言一、计算机结构1.1 计算机组成结构1.2 CPU组成1.3 冯诺依曼结构与哈佛结构二、存储结构2.1 层次化存储结构2.2 Cache三、数据传输控制方式四、总线五、CISC与RISC六、流水线七、校验码八、嵌入式前言 本文主要介绍计算机组成与体系结构。 一、计算机结构 1.1 计…...

既然有HTTP协议,为什么还要有RPC

既然有HTTP协议&#xff0c;为什么还要有RPC&#xff1f; 从TCP聊起 作为一个程序员&#xff0c;假设我们需要在A电脑的进程发一段数据到B电脑的进程&#xff0c;我们一般会在代码里使用socket进行编程。 这时候&#xff0c;我们可选项一般也就TCP和UDP二选一。TCP可靠&…...

【新2023】华为OD机试 - 选座位(Python)

华为 OD 清单查看地址:blog.csdn.net/hihell/category_12199275.html 选座位 题目 疫情期间需要大家保证一定的社交距离 公司组织开交流会议,座位有一排共N个座位 编号分别为[0...n-1] 要求员工一个接着一个进入会议室 并且还可以在任何时候离开会议室 每当一个员工进入时…...

数据分析与SAS学习笔记4

INPUT语句&#xff1a;格式修饰符&#xff1a; “:” 修饰符。表示从下一个非空格列读入数据&#xff0c;直到:1 遇到再下一个空格列&#xff1b; 2 读到预先定义的变量长度&#xff1b; 3 数据行结束。哪个先出现就在哪儿结束。 “&” 修饰符。表示从下一个非空格列读入…...

Xepor:一款针对逆向工程和安全分析的Web路由框架

关于Xepor Xepor是一款专为逆向分析工程师和安全研究专家设计的Web路由框架&#xff0c;该工具可以为研究人员提供类似Flask API的功能&#xff0c;支持以人类友好的方式拦截和修改HTTP请求或HTTP响应信息。 该项目需要与mitmproxy一起结合使用&#xff0c;用户可以使用Xepor…...

Hadoop核心组成和生态系统简介

一、Hadoop的概念 Hadoop是一个由Apache基金会所开发的分布式系统基础架构。用户可以在不了解分布式底层细节的情况下&#xff0c;开发分布式程序。充分利用集群的威力进行高速运算和存储。Hadoop实现了一个分布式文件系统&#xff08; Distributed File System&#xff09;&am…...

Flutter-Charts_painter大数据量绘制性能优化-数据收敛

Flutter-Charts_painter大数据量绘制性能优化-数据收敛 1、背景介绍 HRV测量仪器上传的数据&#xff0c;每秒有250个数据&#xff0c;业务上需要测量180秒&#xff0c;预计有3w-5w个数据点需要绘制到折线图上去。Charts_painter绘制这么大的数据是时候会有些卡顿&#xff0c;…...

使用 GeForce Experience 更新 NVIDIA GPU 显卡驱动

使用 GeForce Experience 更新 NVIDIA GPU 显卡驱动1. NVIDIA GeForce Experience 2. 驱动程序 -> 检查更新文件 3. 下载 如果有可用的新版驱动的话&#xff0c;点击后方的 [下载] 按钮即可。 4. 安装 [快速安装] 按照默认设置安装驱动&#xff0c;[自定义安装] 可以自行…...

Java泛型的<? super T>,<? extend T>的区别

&#xff1f; extends T ? extends T 描述了通配符上界, 即具体的泛型参数需要满足条件: 泛型参数必须是 T 类型或它的子类, 例如: List<? extends Number> numberArray new ArrayList<Number>(); // Number 是 Number 类型的 List<? extends Number>…...

如何做出好看的Excel可视化图表?

可视化死磕excel是不行的&#xff0c;作为数据分析行业的偷懒大户&#xff0c;分享一些我在可视化工具上的使用心得&#xff0c;总结了三大类&#xff1a;快速出图类、专业图表类、高端大屏类。个人经验&#xff0c;大家按需采纳&#xff1a; 一、快速出图类 如果你只是因为偶…...

智能吸吹一体式方案设计特点

一、家用吸吹一体吸尘器方案研发设计要素&#xff1a; 1.小巧的机身设计&#xff0c;一手掌握&#xff0c;无论是床底、沙发下还是家具缝隙之中都能够使用。 2.无线&#xff0c;插电两用&#xff0c;在家方便可插电使用。内置可充电锂电池&#xff0c;充满电也可无线使用。 3.采…...

CSDN 编辑器 Marddown 语法备忘

原文链接&#xff1a;https://blog.csdn.net/blogdevteam/article/details/103478461 本文对其二次加工&#xff0c;增加渲染样式、补充例程、添加未收录的常用语法。 CSDN Markdown 编辑器遵循 CommonMark spec 语法规范。 快捷键 撤销&#xff1a;Ctrl/Command Z 重做&…...

回归预测 | MATLAB实现NGO-BiLSTM北方苍鹰算法优化双向长短期记忆网络多输入单输出回归预测

回归预测 | MATLAB实现NGO-BiLSTM北方苍鹰算法优化双向长短期记忆网络多输入单输出回归预测 目录回归预测 | MATLAB实现NGO-BiLSTM北方苍鹰算法优化双向长短期记忆网络多输入单输出回归预测预测效果基本介绍程序设计参考资料预测效果 基本介绍 Matlab实现NGO-BiLSTM北方苍鹰算法…...

微网站与手机网站/口碑营销5t理论

http://www.cnblogs.com/chenergougou/p/7056557.html openstack RPC通信 OpenStack 的主要组件有 Nova、Cinder、Neutron、Glance 等&#xff0c;分别负责云平台的计算、存储、网络资源管理。openstack 各组件之间是通过 REST 接口进行相互通信&#xff0c;而各组件内部则采用…...

做网站被骗没有居住证能不能告他/小网站怎么搜关键词

ThinkPHP 5.0 MongoDb驱动 首先安装官方的mongodb扩展&#xff1a; http://pecl.php.net/package/mongodb 找到对应的php版本的扩展 然后&#xff0c;配置应用的数据库配置文件database.php的type参数为&#xff1a; type > \think\mongo\Connection, 即可正常使用M…...

苏州网站建设系统方案/怎么创建自己的游戏网站

在CAD作图过程中&#xff0c;肯定会遇到一些各种各样的问题&#xff0c;那么我们该怎样去解决那些问题呢&#xff1f;别急&#xff0c;今天小编就跟大家来分享一些经常出现的问题以及解决办法。1.将CAD默认保存文件设置为最低我们只需在绘图界面输入OP&#xff0c;弹出对话框后…...

免费入驻的网站设计平台/百度竞价推广点击器

看了标题&#xff0c;可能很多人会心生疑问&#xff0c;比如……DAX语言是什么&#xff1f;答&#xff1a;……说来话长&#xff0c;简而言之&#xff0c;DAX&#xff0c;即数据分析表达式语言&#xff0c;是PowerPivot和SQL Server分析服务表格式的语言&#xff0c;具有强悍而…...

中山移动网站建设报价/世界杯大数据

最近在看李沐的实用机器学习课程&#xff0c;讲到regression问题的loss的时候有弹幕问&#xff1a;“为什么要平方&#xff1f;”如果是几年前学生问我这个问题&#xff0c;我会回答&#xff1a;“因为做回归的时候的我们的残差有正有负&#xff0c;取个平方求和以后可以很简单…...

建设网站的基本知识/怎样推广一个产品

目录 一、SD卡简介 1、SDIO简介 2.SD卡物理结构 二、STM32CubeMX建立工程 1.配置管脚 2.点击FATFS&#xff0c;勾选User-defined 3.SYS配置 4.GPIO配置 5.SPI1配置 6.USART1配置 7.时钟树配置 8.修改堆栈大小 三、程序编写 1.源代码下载 2.修改接口里面的内容映…...