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

C++进阶-->继承(inheritance)

1. 继承的概念及定义

1.1 继承的概念

继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要手段,他允许我们在保证原有类的特性基础上还进行扩展,通过继承产生的类叫做派生类(子类),被继承的类叫做基类(父类)。继承呈现了面向对象程序设计的层次结构。和我们之前Date类那里重载运算符的那块有异曲同工之妙,重载运算符那里的实现是函数的复用,而继承则是类设计层次的复用。

ok, 当我们想创建两个类一个是学生,一个是教师,他们都有一些共同的特点例如名字、地址、电话号码、年龄等等的时候,但他们也有不同的一些特点,例如学生有学号,老师有职称等等,我们就可以用继承来实现,创建一个父类Person储存他们的共同特点,然后再对父类进行继承出新的子类即可;

语法为:

class Person{};

class Teacher: public: Person{};

class Student: public: Person{};

当我们想实现一个Student类和Teacher类的时候会有一些相同的信息;如下代码所示:

#include<iostream>
using namespace std;class Student
{
public:// 进⼊校园/图书馆/实验室刷⼆维码等⾝份认证void identity(){// ...}// 学习void study(){// ...}
protected:string _name = "peter"; // 姓名string _address; // 地址string _tel; // 电话int _age = 18; // 年龄int _stuid; // 学号
};
class Teacher
{
public:// 进⼊校园/图书馆/实验室刷⼆维码等⾝份认证void identity(){// ...}// 授课void teaching(){//...}
protected:string _name = "张三"; // 姓名int _age = 18; // 年龄string _address; // 地址string _tel; // 电话string _title; // 职称
};
int main()
{return 0;
}

那么我们就可以用继承进行解决代码如下:

#include<iostream>
using namespace std;class Person
{
public:// 进⼊校园/图书馆/实验室刷⼆维码等⾝份认证void identity(){cout << "void identity()" << _name << endl;}
protected:string _name = "张三"; // 姓名string _address; // 地址string _tel; // 电话int _age = 18; // 年龄
};class Student : public Person
{
public:// 学习void study(){// ...}
protected:int _stuid; // 学号
};class Teacher : public Person
{
public:// 授课void teaching(){//...}
protected:string title; // 职称
};
int main()
{Student s;Teacher t;s.identity();t.identity();return 0;
}

这样Student 和Teacher都有Person类的成员例如name、address、tel,而有不需要我们再过多写;

首先又在这里提一嘴就是成员变量被protected修饰的话就代表他的子类或者内部类可以使用,而在类外或者派生类(子类)外都不可以使用,private则是子类和类外都不能使用;


1.2 继承的定义

定义的格式:

如下图可见:

1. 如果基类(父类)的成员是private的话,在派生类(子类)不可以被访问,但是这些成员也一样会被继承到派生类去,只是不能访问而已。

2. 基类(父类)的成员是protected的话,在派生类(子类)中可以被访问。而protected关键词其实就是因为继承才出现的。

3. 继承方式,一般是按最小级别的来,级别如:public > protected > private ,如果说继承方式是public的话,基类成员是private修饰的,那么基类的成员访问限定符按最小级别来即private;如果说继承方式是private的话,无论基类成员是public还是protected,基类的访问限定符都为private。

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

5. 一般都是用public,便于维护;


1.3 继承类模板

顾名思义继承一个类模板;如下代码和注释来看:

#include<iostream>
#include<vector>
#include<list>
#include<deque>
#define Container std::vector
using namespace std;namespace lwt
{//template<class T>//class vector//{};// stack和vector的关系,既符合is-a,也符合has-a//is-a是说stack底层实现就是vector//has-a是说包含关系,即vector可以被stack继承,因为stack的特性包含vector的特性template<class T>class stack : public std::vector<T>{public://👇如果说我们直接调用的push_back(x);的话会出错,因为按需实例化的时候//push_back在本类里面找不到然后就会进到父类里面找,但都没找到,所以我们要指定一下//类域即vector<T>::void push(const T& x){// 基类是类模板时,需要指定⼀下类域,// 否则编译报错:error C3861: “push_back”: 找不到标识符// 因为stack<int>实例化时,也实例化vector<int>了// 但是模版是按需实例化,push_back等成员函数未实例化,所以找不到//push_back(x);vector<T>::push_back(x);}void pop(){vector<T>::pop_back();}const T& top(){return vector<T>::back();}bool empty(){return vector<T>::empty();}};//下面是上面的一个新用法//我们可以使用宏在头部定义一个Container放置std::vectortemplate<class T>class stack : public Container<T>{public:void push(const T& x){vector<T>::push_back(x);}void pop(){vector<T>::pop_back();}const T& top(){return vector<T>::back();}bool empty(){return vector<T>::empty();}};

这里再来讲一下里面为什么要用vector<T>::push_back,因为模板是遵守按需实例化的规则来的,class stack : public std::vector<T>,如果我们我们实例化stack<int>,那就只实例化了vector<int>,编译器不知道我们还要实例化里面的功能,这里只是单纯实例化了一个vector<int>对象,所以我们需要指定一下vector<T>域内的push_back即可;


2. 基类和派生类之间的转换

  • public继承的派生类(子类)对象可以给基类(父类)的对象、指针和引用赋值。但不是把派生类(子类)对象的所有成员都赋值给基类(父类)对象,而是把原先属于基类部分的成员赋值给基类对象;这个过程称为切割或者切片;很好理解,就是把派生类内不是从基类继承来的成员切割掉;
  • 基类的对象不能赋值给派生类的对象;
  • 但是如果那个基类的对象的指针原先就是指向派生类的指针的话,那还是可以通过强制类型转换赋值给派生类对象的,但是这里使用到一个dynamic_cast,这里只是演示一下;如下代码所示:
    #include<iostream>using namespace std;
    class Person
    {
    protected://多态后面会说virtual void func(){}
    public:Person(const string& name, const string& sex, int age):_name(name),_sex(sex),_age(age){cout << "Person(const string& name, const string& sex, int age)" << endl;cout << "name:> " << _name << endl;cout << "sex:> " << _sex << endl;cout << "age:> " << _age << endl;}string _name; // 姓名string _sex; // 性别int _age; // 年龄
    };class Student :public Person
    {
    public:Student(const string& name="lwt", const string& sex="man", int age=20):Person(name, sex, age){}int _No; //学号
    };int main()
    {Student sobj;//子类对象可以赋值给父类对象/指针/引用//这样就是上面所说的切割,即会把非父类对象的部分切割然后//把是父类对象的部分赋值给父类Person pobj = sobj;Person* pp = &sobj;Person& rp = sobj;//基类的指针或者引⽤可以通过强制类型转换赋值给派⽣类的指针或者引⽤。但是必须是基类的指针//是指向派⽣类对象时才是安全的。这⾥基类如果是多态类型,可以使⽤RTTI(Run - Time Type//Information)的dynamic_cast 来进⾏识别后进⾏安全转换。(ps:这个我们后⾯类型转换章节再//单独专⻔讲解,这⾥先提⼀下)Student* sp1 = dynamic_cast<Student*>(pp);cout << sp1<< endl;cout << pp << endl;pp = &pobj;Student* sobj2 = dynamic_cast<Student*>(pp);//2.父类对象不能赋值给子类对象,这里会编译报错//sobj = (Student)pobj;return 0;
    }

    👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇

    运行结果为:

 这里需要提一点的就是,在派生类想要初始化基类的话需要调用基类的构造函数,不可以直接使用基类的成员变量在派生类的初始化链表初始化;


3. 继承的作用域

3.1 隐藏

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

2. 派生类和基类中如果有同名的成员的话,那么就会屏蔽掉基类的成员访问,这种就称作隐藏;那如果我们在派生类想要访问基类中被隐藏的成员我们就可以通过指定访问域进行访问例如:基类::基类成员即可;

3. 如果是成员函数的话,构成隐藏的条件只需要一个即函数名相同,即使他们的参数不相同也不会构成重载,照样构成隐藏;如下代码所示:

#include<iostream>
using namespace std;class Person
{
public:void Fun(){cout << "PersonFunc()" << endl;}void test(int a){cout << "Persontest()" << endl;}
protected:string _name = "小李子"; // 姓名int _num = 111; // 身份证号
};//隐藏即如果基类和派生类有同名的成员的话
//基类的成员就会被隐藏,只是用派生类的成员
//如果我们想使用基类里面的话我们就需要指定类域
//即可;//如果说有函数名相同的则会直接隐藏基类的函数,不管他们参数是否一样
//不会构成重载
//只会被隐藏掉class Student : public Person
{
public:void Print(){cout << _num << endl;cout << Person::_num << endl;}void Func(){cout << "StudentFunc()" << endl;}void test(){cout << "Studenttest()" << endl;}protected:int _num = 999; // 学号
};int main()
{Student s1;s1.Print();s1.Func();s1.Person::Fun();//报错//s1.test(1);s1.Person::test(1);return 0;
}

👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇

运行结果为:


看完这个知识点我们直接就来两道面试题;如下图

#include<iostream>
using namespace std;
class A
{
public:void fun(){cout << "func()" << endl;}
};
class B : public A
{
public:void fun(int i){cout << "func(int i)" << i << endl;}
};
int main()
{B b;b.fun(10);b.fun();return 0;
};

答案:A,A;

解析:首先上面说了,只要函数名相同就构成隐藏,不管他参数相同还是不同,都不会构成重载;所以第一题选A。

第二题:由于是构成隐藏关系,那我们想访问那个无参的func的话就必须显式调用即b.A::func();指定一定访问域,不然就报错;


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

默认的意思就是指我们不写,编译器会帮我们自动生成一个;

1. 基类如果没有默认构造的话,那么在派生类的构造函数里需要调用基类的构造函数对基类的成员进行初始化,调用基类的构造函数就类似于匿名对象一样,但这里不叫匿名对象;如下代码所示:

#include<iostream>
using namespace std;class Person
{
public:Person(const string& name	):_name(name){cout << "Person()" << endl;}protected:string _name;
};class Student:public Person
{
public:Student(const string& name, int num):Person(name),_num(num){cout << "Student()" << endl;}protected:int _num;
};int main()
{Student s1("lwt", 12);return 0;
}

👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇

运行结果为:


2. 拷贝构造的也是一样,派生类的拷贝构造函数必须调用基类的拷贝构造完成基类的初始化;

#include<iostream>
using namespace std;class Person
{
public:Person(const string& name	):_name(name){cout << "Person()" << endl;}Person(const Person& p):_name(p._name){cout << "Person拷贝构造调用" << endl;}protected:string _name;
};class Student:public Person
{
public:Student(const string& name, int num):Person(name),_num(num){cout << "Student()" << endl;}// 严格说Student拷贝构造默认生成的就够用了// 如果有需要深拷贝的资源,才需要自己实现Student(const Student& s1):Person(s1),_num(s1._num){cout << "Student拷贝构造调用" << endl;}protected:int _num;
};int main()
{Student s1("lwt", 12);Student s2(s1);return 0;
}

👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇

运行结果为:


3. 派生类的operator=必须调用基类的operator=完成基类的赋值。但需要注意的是派生类的operator=隐藏了基类的operator=,所以要显示调用基类的operator=。

#include<iostream>
using namespace std;class Person
{
public:Person(const string& name	):_name(name){cout << "Person()" << endl;}Person(const Person& p):_name(p._name){cout << "Person拷贝构造调用" << endl;}Person& operator=(const Person& p){cout << "Person& operator=(const Person& p)" << endl;if (this != &p){_name = p._name;}return *this;}
protected:string _name;
};class Student:public Person
{
public:Student(const string& name, int num):Person(name),_num(num){cout << "Student()" << endl;}// 严格说Student拷贝构造默认生成的就够用了// 如果有需要深拷贝的资源,才需要自己实现Student(const Student& s1):Person(s1),_num(s1._num){cout << "Student拷贝构造调用" << endl;}void print(){cout << _num << endl;cout << _name << endl;}Student& operator=(const Student& s1){if (this != &s1){//父类和子类的operator=构成隐藏关系Person::operator=(s1);_num = s1._num;}return *this;}protected:int _num;
};int main()
{Student s1("lwt", 12);Student s2(s1);Student s3("lll", 15);cout << endl;s2.print();cout << endl;s2 = s3;s2.print();return 0;
}

👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇

运行结果为:

有一个很巧妙的点就在于,你看在Student内重载operator=那里的Person::operator=(s1),如果我们没有学到基类和派生类之间的转换的话我们不懂为什么Person内重载的operator的参数是Person,而在这里我们传了类型为Student的s1进去,这里就造成了切割或切片。


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

#include<iostream>
using namespace std;class Person
{
public:Person(const string& name	):_name(name){cout << "Person()" << endl;}Person(const Person& p):_name(p._name){cout << "Person拷贝构造调用" << endl;}protected:string _name;
};class Student:public Person
{
public:Student(const string& name, int num):Person(name),_num(num){cout << "Student()" << endl;}// 严格说Student拷贝构造默认生成的就够用了// 如果有需要深拷贝的资源,才需要自己实现Student(const Student& s1):Person(s1),_num(s1._num){cout << "Student拷贝构造调用" << endl;}void print(){cout << _num << endl;cout << _name << endl;}protected:int _num;
};int main()
{Student s1("lwt", 12);return 0;
}

👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇

运行结果为:


5. 析构函数的调用,如果说这里面没有动态申请空间的话,默认的析构函数也够用了,如果动态申请了的话我们就需要写析构函数清理申请的内存,那问题又来了,我们不仅要清理派生类里面的空间,还要清理基类内的空间,那么我们就需要写两个析构函数,但是呢问题又来了,基类的析构和派生类的析构构成隐藏,原因是无论析构函数的名字怎么样,最后都会被编译器转为一个名为destructor()的函数,所以会导致隐藏,那么我们就需要指定一下作用域;如下代码所示:

#include<iostream>
using namespace std;
class Person
{
public:Person(const char* name = "胡图图"): _name(name){cout << "Person()" << endl;}Person(const Person& p): _name(p._name){cout << "Person(const Person& p)" << endl;}~Person(){cout << "~Person()" << endl;}
protected:string _name; // 姓名
};class Student : public Person
{
public:Student(const char* name, int num, const char* addrss):Person(name), _num(num), _addrss(addrss){}// 严格说Student拷贝构造默认生成的就够用了// 如果有需要深拷贝的资源,才需要自己实现Student(const Student& s):Person(s), _num(s._num), _addrss(s._addrss){// 深拷贝}// 严格说Student析构默认生成的就够用了// 如果有需要显示释放的资源,才需要自己实现// 析构函数都会被特殊处理成destructor() ~Student(){// 子类的析构和父类析构函数也构成隐藏关系// 规定:不需要显示调用,子类析构函数之后,会自动调用父类析构// 这样保证析构顺序,先子后父,显示调用取决于实现的人,不能保证// 先子后父cout<<"~Student()"<<endl;Person::~Person();delete _ptr;}
protected:int _num = 1; //学号string _addrss = "翻斗花园";int* _ptr = new int[10];
};int main()
{Student* ptr = new Student("胡图图",10,"翻斗花园");delete ptr;return 0;
}

👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇

运行结果为:

这里为什么会有两个~Person呢?原因是其实派生类的析构函数调用后会自动调用基类的析构函数,所以不需要我们写;我们可以把~Student里面的Person::~Person()删掉即可;

👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇

运行结果为:

最后总结一下:一般如果没有深拷贝的话拷贝构造和赋值运算符重载不需要我们自己写,用默认的就行,析构函数也是;然后析构函数的调用顺序是先子后父


5. 实现一个不能被继承的类

方法一:让构造函数的访问限定符为private,这样就无法调用了。

#include<iostream>
using namespace std;class Person
{
public:private:Person(){}
};class Student : public Person
{
public:
};
int main()
{Student s1;return 0;
}

方法二:c++11新加的关键字final,final加到基类的类名后就不能被继承了。


6. 继承和友元

友元的关系不能被继承,说明基类的友元不能访问派生类的私有保护成员;举个很简单的例子方便记忆,“父亲的朋友不是你的朋友”;如下代码所示:


7. 继承与静态成员

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

#include<iostream>
using namespace std;class Person
{
public:string _name;static int _count;};int Person::_count = 0;class Student:public Person
{
protected:int _stuNum;
};int main()
{Student s;Person p;//地址不一样说明已经继承了cout << &s._name << endl;cout << &p._name << endl;//地址一样说明只有一份cout << &s._count << endl;cout << &p._count << endl;return 0;
}

👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇  👇

运行结果为:


7. 多继承以及菱形继承的问题

7.1 继承模型

单继承:一个派生类只有一个基类。

多继承:一个派生类有两个或两个以上的基类,“我爸”有一个Son的基类和Dad的基类,多继承对象在内存中的模型是先继承的基类放在前面,后继承的放后面。

菱形继承:是多继承的一种特殊情况,可能祖师爷那会喝醉了没想到这个情况吧。菱形继承会导致数据冗余和二义性的问题,Assistant里面有两份Person,因为Student里面有一份Person,Teacher里面也有一份Person;

#include<iostream>
using namespace std;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;
};int main()
{Assistant a;a._name() = "胡图图";
}

如果我们想解决这个问题的话可以指定访问指定的基类成员就可以了;


7.2 虚继承

有了多继承,菱形继承就无法避免最好不要实现出来,但我们也可以在其中做出一些操作;在两个会继承到同一个基类的派生类处加关键字virtual即可;如下代码所示:

#include<iostream>
using namespace std;class Person
{
public:string _name;
};class Student :public virtual Person
{
protected:int _num;
};class Teacher :public virtual Person
{
protected:int _id;
};class Assistant :public Student, public Teacher
{
public:
protected:string _majorCourse;
};int main()
{Assistant a;a._name = "胡图图";//a.Student::_name = "胡图图";//a.Teacher::_name = "胡英俊";return 0;
}

这串代码就可以执行了;而这个东西的原理就是把那些继承的数据,通过虚基表和虚基指针来管理这些共享的数据,从而避免了数据的冗余;简单点理解就是放在一个公共区域共同使用。


8. 继承和组合

继承是子类继承了父类的特性,可以说子类其实就是一个特殊的父类,而组合则是将另一个类当做自己的成员变量进行使用;

继承是is-a的关系,举个例子,例如狗是一个动物,那么狗就是子类,而动物就是父类,而狗有动物的所有特性,即是有个新的类需要一个类的所有特性的时候就可以使用继承。

而组合是has-a,这里也举个例子就是汽车有一个轮子,那么我们有一个class Car{class wheels{};};,即有个类需要某些特定的功能的时候则可以使用组合。组合可以很好地保护类的安全性不破坏封装;


END!

相关文章:

C++进阶-->继承(inheritance)

1. 继承的概念及定义 1.1 继承的概念 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要手段&#xff0c;他允许我们在保证原有类的特性基础上还进行扩展&#xff0c;通过继承产生的类叫做派生类&#xff08;子类&#xff09;&#xff0c;被继承的类叫做基类&a…...

可视化项目 gis 资源复用思路(cesium)

文章目录 可视化项目 gis 资源复用思路底图、模型替换思路具体操作 可视化项目 gis 资源复用思路 背景&#xff1a; A项目的底图、模型 是现在在做的 B项目所需要的&#xff0c;现在要把 B项目的底图之类的替换成 A系统的 底图、模型替换思路 观察可访问系统的 gis 相关网络请…...

SQL实战测试

SQL实战测试 &#xff08;请写下 SQL 查询语句&#xff0c;不需要展示结果&#xff09; 表 a DateSalesCustomerRevenue2019/1/1张三A102019/1/5张三A18 1. **用一条 ** SQL 语句写出每个月&#xff0c;每个销售有多少个客户收入多少 输出结果表头为“月”&#xff0c;“销…...

Java 基础教学:基础语法-变量与常量

变量 变量是程序设计中的基本概念&#xff0c;它用于存储信息&#xff0c;这些信息可以在程序执行过程中被读取和修改。 变量的声明 在Java中&#xff0c;声明变量需要指定变量的数据类型以及变量的名称。数据类型定义了变量可以存储的数据种类&#xff08;例如整数、浮点数…...

vue3使用element-plus手动更改url后is-active和菜单的focus颜色不同步问题

在实习&#xff0c;给了个需求做个新的ui界面&#xff0c;遇到了一个非常烦人的问题 如下&#xff0c;手动修改url时&#xff0c;is-active和focus颜色不同步 虽然可以直接让el-menu-item:focus为白色能解决这个问题&#xff0c;但是我就是想要有颜色哈哈哈&#xff0c;有些执…...

每天五分钟深度学习框架pytorch:从底层实现一元线性回归模型

本文重点 本节课程我们继续搭建一元线性回归模型,不同的是这里我们不使用pytorch框架已经封装好的一些东西,我们做这个目的是为了更加清楚的看到pytorch搭建模型的本质,为了更好的理解,当然实际中我们还是使用pytorch封装好的一些东西,不要重复造轮子。 模型搭建 #定义…...

编辑器加载与AB包加载组合

解释&#xff1a; 这个 ABResMgr 类是一个资源加载管理器&#xff0c;它用于整合 AB包&#xff08;Asset Bundle&#xff09;资源加载和 编辑器模式资源加载。通过这个管理器&#xff0c;可以根据开发环境选择资源加载方式&#xff0c;既支持 运行时使用Asset Bundle加载&…...

【c++】vector中的back()函数

nums.back() 是 C 中 std::vector 类的一个成员函数&#xff0c;用于获取数组&#xff08;向量&#xff09;中的最后一个元素。以下是一些关于 nums.back() 的详细解释和示例使用&#xff1a; 1. 功能 nums.back() 返回数组 nums 中的最后一个元素。如果数组为空&#xff0c;…...

[分享] SQL在线编辑工具(好用)

在线SQL编写工具&#xff08;无广告&#xff09; - 在线SQL编写工具 - Web SQL - SQL在线编辑格式化 - WGCLOUD...

element-ui隐藏表单必填星号

// 必填星号在前显示 去掉 .el-form-item.is-required:not(.is-no-asterisk) > .el-form-item__label:before { content: !important; margin-right: 0px!important; } // 必填星号在结尾显示 .el-form-item.is-required:not(.is-no-asterisk) > .el-form-item__labe…...

自动驾驶系列—激光雷达点云数据在自动驾驶场景中的深度应用

&#x1f31f;&#x1f31f; 欢迎来到我的技术小筑&#xff0c;一个专为技术探索者打造的交流空间。在这里&#xff0c;我们不仅分享代码的智慧&#xff0c;还探讨技术的深度与广度。无论您是资深开发者还是技术新手&#xff0c;这里都有一片属于您的天空。让我们在知识的海洋中…...

C#删除dataGridView 选中行

关键在于&#xff1a;从最后一行开始删除。 从前往后删只能删除其中一半&#xff0c;我理解是再remove行的时候dataGridView内部行序列发生了变化&#xff0c;包含在选中行中的特定行会被忽略&#xff0c;从后往前删就可避免这个问题&#xff0c;最后一行的行号影响不到前面的…...

K8S调度不平衡问题分析过程和解决方案

不平衡问题排查 问题描述&#xff1a; 1、业务部署大量pod(据反馈&#xff0c;基本为任务型进程)过程中&#xff0c;k8s node内存使用率表现不均衡&#xff0c;范围从80%到百分之几&#xff1b; 2、单个node内存使用率超过95%&#xff0c;仍未发生pod驱逐&#xff0c;存在node…...

Python中类、继承和方法重写的使用

&#x1f600;前言 本篇博文将介绍如何定义类、创建类的实例、访问类的成员、使用属性、实现继承及方法重写&#xff0c;希望你能够喜欢 &#x1f3e0;个人主页&#xff1a;晨犀主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是晨犀&#xff0c;希望我的文章可以…...

【Neo4j】- 轻松入门图数据库

文章目录 前言-场景一、Neo4j概述二、软件安装部署1.软件下载2.软件部署3.软件使用4.语法学习 总结 前言-场景 这里用大家都了解的关系数据与图数据据库对比着说,更加方便大家理解图数据库的作用 图形数据库和关系数据库均存储信息并表示数据之间的关系。但是&#xff0c;关系…...

LeetCode 206 - 反转链表

解题思路 我们可以使用迭代的方法来实现链表的反转&#xff0c;这里我们先介绍迭代的方法。迭代的思路是&#xff1a;从头节点开始&#xff0c;依次将节点的next指针进行反转&#xff0c;使得当前节点的next指向其前一个节点&#xff0c;然后依次向后移动指针&#xff0c;直至…...

AI生成大片,Movie Gen 可以生成长视频并配上完美的音效,带给观众更好的观看体验。

之前的文章中已经给大家介绍了一些关于长视频生成相关的技术&#xff0c;AI生成大片已经越来越近了。感兴趣的小伙伴可以点击下面链接阅读~ Movie Gen 的工作原理可以简单理解为两个主要部分&#xff1a;一个是生成视频的模型&#xff0c;另一个是生成音频的模型。首先&#x…...

Flink on yarn模式下,JobManager异常退出问题

这个问题排除了很久&#xff0c;其中更换了Flink版本&#xff0c;也更换了Hadoop版本一直无法解决&#xff0c;JobManager跑着跑着就异常退出了。资源管理器上是提示运行结束&#xff0c;运行状态是被Kill掉。 网上搜了一圈&#xff0c;都说内存不足、资源不足&#xff0c;配置…...

面对AI算力需求激增,如何守护数据中心机房安全?

随着人工智能&#xff08;AI&#xff09;技术飞速发展&#xff0c;AI算力需求呈现爆发式增长&#xff0c;导致对数据设备电力的需求指数级攀升。这给数据中心带来前所未有的挑战和机遇&#xff0c;从提供稳定的电力供应、优化高密度的部署&#xff0c;到数据安全的隐私保护&…...

Connection --- 连接管理模块

目录 模块设计 模块实现 shared_from_this 模块测试纠错 模块设计 Connection模块是对通信连接也就是通信套接字的整体的管理模块&#xff0c;对连接的所有操作都是通过这个模块提供的接口来完成的。 那么他具体要进行哪些方面的管理呢&#xff1f; 首先每个通信连接都需…...

iconfont图标放置在某个元素的最右边

在网页设计中&#xff0c;如果你想要将iconfont图标放置在某个元素的最右边&#xff0c;你可以通过CSS来实现这个布局。以下是一些基本的CSS代码示例&#xff0c;它们可以帮助你根据不同的布局需求将图标放置在最右边&#xff1a; 内联元素&#xff08;如<span>&#xff…...

Android10 recent键相关总结

目录 初始化流程 点击Recent键流程 RecentsActivity 显示流程 RecentsModel 获取数据管理类 RecentsActivity 布局 已处于Recent界面时 点击recent 空白区域 点击返回键 recent组件配置 Android10 Recent 功能由 System UI&#xff0c;Launcher共同实现。 初始化流程 …...

Ajax:原生ajax、使用FormData的细节问题,数据的载体

人生海海&#xff0c;山山而川&#xff0c;不过尔尔&#xff1b;空空而来&#xff0c;苦苦而过&#xff0c;了了而去 文章目录 原生ajax使用FormData的细节问题数据的载体 原生ajax 执行顺序 创建xhr对象 var xhr new XMLHttpRequest()调用xhr.open(请求方式, url)函数&#…...

【HuggingFace 如何上传数据集 (2) 】国内网络-稳定上传图片、文本等各种格式的数据

【HuggingFace 下载】diffusers 中的特定模型下载&#xff0c;access token 使用方法总结【HuggingFace 下载中断】Git LFS 如何下载指定文件、单个文件夹&#xff1f;【HuggingFace 如何上传数据集】快速上传图片、文本等各种格式的数据 上文的方法因为是 https 协议&#xf…...

GNOME桌面安装dock

Although GNOME Shell integration extension is running, native host connector is not detected. Refer documentation for instructions about installing connector. sudo yum -y install chrome-gnome-shell...

移动app测试有哪些测试类型?安徽软件测试中心分享

科技信息时代&#xff0c;移动app的出现为我们的生活及工作带来了极大的便利。一款app从生产到上线必不可少的就是测试阶段&#xff0c;app测试是保障产品质量和安全的有效手段&#xff0c;那么移动app测试有哪些测试类型呢?安徽软件测试中心又有哪些? 1、功能性测试   需…...

Android 10.0 截屏流程

通常未通过特殊定制的 Android 系统&#xff0c;截屏都是经过同时按住音量下键和电源键来截屏。本篇文章就只讨论使用这些特殊按键来进行截屏。 这里我们就要明白事件是在哪里进行分发拦截的。通过源码的分析&#xff0c;我们发现是在PhoneWindowManager.java 中。 PhoneWindow…...

Axure零基础深入浅出的讲解

在当今的互联网产品设计领域&#xff0c;原型设计已经成为了产品经理、设计师和开发者之间沟通的桥梁。而Axure作为一款功能强大、灵活易用的原型设计工具&#xff0c;正是很多产品经理的得力助手。无论你是产品经理新手&#xff0c;还是资深设计师&#xff0c;Axure都能帮助你…...

PyTorch求导相关

PyTorch是动态图&#xff0c;即计算图的搭建和运算是同时的&#xff0c;随时可以输出结果&#xff1b;而TensorFlow是静态图。 在pytorch的计算图里只有两种元素&#xff1a;数据&#xff08;tensor&#xff09;和 运算&#xff08;operation&#xff09; 运算包括了&#xf…...

Halcon基础-瓶盖带角度的OCR批量识别

Halcon基础-OCR识别 1、OCR识别素材2、创建路径文件3、Halcon代码实现4、运行效果5、资源获取 1、OCR识别素材 这里我准备了7张不同角度的OCR图片&#xff0c;如下所示&#xff1a; 2、创建路径文件 按照下图所示创建全部文件夹和文件&#xff1a; 01用来存放OCR识别原图 c…...

网站建设目的/免费招聘信息发布平台

开始最好是去大公司&#xff0c;趁年轻多学点技术。 贝瑞和康招聘 - 生物信息工程师 生物信息软件工程师 - 博奥生物集团有限公司 医学检测生物信息工程师[只招应.. 生物信息工程师-北京 安诺优达基因科技&#xff08;北京&#xff09;有限公司 生物信息研发工程师-ctDNA方向 北…...

网站建设项目说明书模板/广州网站优化软件

---一个人的世界难免孤寂&#xff0c;走走停停&#xff0c;总悄然无声息 幸好&#xff0c;世界上还有一个她&#xff0c;能够分享彼此的欢乐和哀愁&#xff0c;与她在一起的日子&#xff0c;便是最美好的时光。 你有没有这样的一样知己&#xff0c;她与你一起走过青春年少&…...

做外汇看什么网站/9个成功的市场营销案例

瞌睡龙 2013/05/20 18:370x00 相关背景介绍Clickjacking&#xff08;点击劫持&#xff09;是由互联网安全专家罗伯特汉森和耶利米格劳斯曼在2008年首创的。是一种视觉欺骗手段&#xff0c;在web端就是iframe嵌套一个透明不可见的页面&#xff0c;让用户在不知情的情况下&#…...

无锡网站建设机构/运营推广计划

Brad Feld的一篇文章 The Rise of Developeronomics中提到了“10倍效率的开发者&#xff08;10x developer&#xff09;”的概念&#xff08;伟大的开发者的效率往往比一般的开发者高很多&#xff0c;而不只是一点点&#xff09;&#xff0c;Adam Loving在读了之后受到启发&…...

wordpress a 登录/百度店铺怎么开通

读入一个正整数 n&#xff0c;计算其各位数字之和&#xff0c;用汉语拼音写出和的每一位数字。 输入格式&#xff1a; 每个测试输入包含 1 个测试用例&#xff0c;即给出自然数 n 的值。这里保证 n 小于 10​100​​。 输出格式&#xff1a; 在一行内输出 n 的各位数字之和…...

webstation做网站/seo怎么优化武汉厂商

PHP CURL模拟RESTFul风格 HTTP常规的请求方式:GET,POST,而RESTFull方法有: GET, POST, PUT, PATCH, DELETE等几种。要支持其他方法怎么办? 我们基于PHP强大的CURL函数封装一个:这里我只增加PUT和DELETE,可以扩展: <?php # php curl 封装 namespace Great\lib; i…...