【CPP】类与继承

14 类与继承

  • 在前面我们提到过继承的一些概念,现在我们来回顾一下

打个比方:在CS2中我们把玩家定义为一个类

  • class 玩家:
    • 血量:100
    • 阵营(未分配)
    • 服饰(未分配)
    • 位置(未分配)
    • 武器(未分配)
    • 是否允许携带C4(未分配)
    • 是否拥有C4(未分配)
  • 当对局创建时,会新生成两个类,这两个类继承自"class 玩家"
    • 反恐精英
      • 血量:100(不变)
      • 阵营:反恐精英
      • 服饰:反恐精英
      • 位置(未分配)
      • 武器(未分配)
      • 是否允许携带C4:否
      • 是否拥有C4:否
    • 恐怖分子
      • 血量:100(不变)
      • 阵营:恐怖分子
      • 服饰:恐怖分子
      • 位置(未分配)
      • 武器(未分配)
      • 是否允许携带C4:是
      • 是否拥有C4:是
  • 当用户oldkingnana加入对局时,系统会生成一个类随机继承自反恐精英或者是恐怖分子(我们假设 类:oldkingnana 继承自了反恐精英)
    • oldkingnana
      • 血量:100(不变)
      • 阵营:反恐精英
      • 服饰:反恐精英
      • 位置:反恐精英出生点
      • 武器:野牛(假设用户买了把野牛)
      • 是否允许携带C4:否
      • 是否拥有C4:否
  • 在以上的例子中我们称反恐精英为玩家的子类,玩家为反恐精英的父类,反恐精英继承自玩家这个父类

  • 使用继承这个操作好处多多

    • 因为存在继承这个操作,因此我们不需要重新定义反恐精英或者恐怖分子这样的类,两者相同的部分(血量)全都包括在其 父类:玩家 中,能提高开发效率
    • 当然不仅仅是属性的部分,部分方法也可以修改自父类,如 恐怖分子 只有安装C4这个方法,而在 反恐精英 中就被替换成了拆除C4这种方法
14.1 类继承的语法粗看
class player
{
public:void move(){cout << "move()" << endl;}protected:int health;int weapon;
};//此处是类的继承
//class [子类名] : [继承优先级] [父类名]
class team1 : public player
{
public:void using_C4(){cout << "using_C4()" << endl;}private:bool C4;
};
  • 子类包含父类的所有成员,只是优先级方面需要着重考虑,及重点研究[继承优先级]
以public优先级继承以protected优先级继承以private优先级继承
父类public标签的成员在子类中为public在子类中为protected在子类中为private
父类protected标签的成员在子类中为protected在子类中为protected在子类中为private
父类private标签的成员在子类中不可访问在子类中不可访问在子类中不可访问
  • 一般情况下常用的也就标记的三个,一般使用public继承就行了,很少会用其他方式继承,况且其他的写多了可读性也会变差,增加debug难度
14.2 简单了解继承在代码中的具体实现方式
14.2.1 普通类作为父类
  • 回到上面CS的例子,我们可以简单写一个类出来
class player
{
public:void move(){cout << "move()" << endl;}protected:int health;int weapon;
};//以下就是类"team1",继承自"player"
class team1 : public player
{
public:void using_C4(){cout << "using_C4()" << endl;}private:bool C4;
};int main()
{team1 t1;return 0;
}
  • (编译通过)
14.2.2 模板类作为父类
template<class T>
class A
{
public:A():_a(1){cout << "A()" << endl;}void func1(T& val){cout << val << endl;}private:int _a;
};template<class T>
class B : public A<T>
{
public:B():_b(2){}void func2(){//子类使用父类的成员函数的时候需要声明类域,具体原因下面会提到A<T>::func1(_b);//A<T>::func1(1.1f);}private:int _b;
};
  • 关于声明类域的原因:
    • 模板在实例化的时候只会按需实例化,比方说上面我想实例化类B,使用B b;来实例化,但却只是实例化了其构造函数,func2()其实并没有被实例化,而实例化B必定会实例化A,但实例化A也只是实例化了构造函数,此时我想在B的成员函数中调用函数func1(),但编译器不知道func1()A的成员函数(因为func1()压根就没有实例化啊),所以找不到
    • 如果未来开发中遇到了"继承链"的情况,而每个"祖先节点"似乎都有同名的成员函数,此时调用的时候就不知道应该用哪个成员函数,所以子类调用"祖先类"的成员函数的时候,一定要指定类域
14.2.3 模板类的继承的应用
  • 例如我们可以很简单地就实现一个栈(没写完)
template<class T>
class myStack : public vector<T>
{
public:void push(const T& val){vector<T>::push_back(val);}void pop(){vector<T>::pop_back();}void top(){return vector<T>::back();}
};
14.3 父类和子类对象的赋值兼容转换
  • 简单来讲就是子类对象可以被允许赋值给父类对象,包括父类对象类型的引用和指针
class person
{
public:person(): _num(111), _name("zhangsan"), _sex("male"), _age(18){}protected:int _num;string _sex;int _age;public:string _name;
};class student : public person
{
public:student(): _school_id("12345"){}
protected:string _school_id;
};int main()
{student st;//这里复制过去的是属于父类对象的一部分,属于子类对象的就没有赋值过去person p1 = st;//指向子类对象中属于父类对象的那一部分person* p2 = &st;//引用子类对象中属于父类对象的那一部分person& p3 = st;//p3引用的是st的一部分,所以修改p3也会导致st被修改p3._name = "lisi";cout << st._name << endl;//输出"lisi"return 0;
}

请添加图片描述

  • Ps:父类不可以赋值给子类,这会导致子类有成员变量不确定,语法上是不允许的,不过有方法让父类指针/引用赋值给子类指针/引用
14.4 作用域的隐藏规则
  • 父类和子类的作用域都是独立的
  • 当父类和子类中同时存在同名的成员变量的时候,父类的成员变量将会被隐藏,如果需要调用的话就得指定类域
  • 如果父类和子类中存在相同名称的成员函数的时候,父类的成员函数会被隐藏,并不会构成重载
  • 最好不要触发作用于的隐藏规则
class person
{
public:person(): _num(111), _name("zhangsan"), _sex("male"), _age(18){}void func(){cout << "person::func()" << endl;}protected:int _num;string _sex;int _age;public:string _name;
};class student : public person
{
public:student(): _school_id("12345"), _num(666), _name("wangwu"){}void func(int x){cout << "student::func()" << endl;}protected:string _school_id;int _num;
public:string _name;
};int main()
{student st;cout << st._name << endl;cout << st.person::_name << endl;st.func(1);st.person::func();//对于隐藏的成员函数的错误使用方式://(因为person的func被隐藏了,所以需要指定类域来调用)//st.func();return 0;
}
  • 注意,这里这两个func()构成隐藏而不是重载!!!
14.5 继承与其他默认成员函数
  • Ps:阅读本小节时,我么们可以将父类当作一个整体看待
14.5.1 关于默认构造函数
class person
{
public:person(int num = 777, string name = "zhangsan", string sex = "male", int age = 18): _num(num), _name(name), _sex(sex), _age(age){}void func(){cout << "person::func()" << endl;}person(const person& p): _num(p._num), _name(p._name), _sex(p._sex), _age(p._age){}protected:int _num;string _sex;int _age;public:string _name;
};class student : public person
{
public:student(string school_id = "12345", int num = 666, string name = "wangwu", int age = 18, string sex = "male"): _school_id(school_id), _num(1), _name(name), person(num, name, sex, age)//子类的默认构造中,需要单独对person进行构造,如果不这么做,person就会调用自己的默认构造函数//如果person没有默认构造函数,就会报错{cout << person::_num << endl;}void func(int x){cout << "student::func()" << endl;}student(const student& st):_school_id(st._school_id), _num(st._num), _name(st._name), person(st){}protected:string _school_id;int _num;
public:string _name;
};int main()
{student st("778899", 444, "oldking");student st1(st);return 0;
}//输出: 444
  • 以下是student子类的默认构造不单独对父类进行构造的情况
class person
{
public:person(int num = 777, string name = "zhangsan", string sex = "male", int age = 18): _num(num), _name(name), _sex(sex), _age(age){}void func(){cout << "person::func()" << endl;}protected:int _num;string _sex;int _age;public:string _name;
};class student : public person
{
public:student(string school_id = "12345", string name = "wangwu", int age = 18, string sex = "male"): _school_id(school_id), _num(1), _name(name){cout << person::_num << endl;}void func(int x){cout << "student::func()" << endl;}protected:string _school_id;int _num;
public:string _name;
};int main()
{student st("778899", 444, "oldking");return 0;
}//输出: 777
14.5.2 关于拷贝构造
class person
{
public:person(int num = 777, string name = "zhangsan", string sex = "male", int age = 18): _num(num), _name(name), _sex(sex), _age(age){}void func(){cout << "person::func()" << endl;}person(const person& p): _num(p._num), _name(p._name), _sex(p._sex), _age(p._age){}protected:int _num;string _sex;int _age;public:string _name;
};class student : public person
{
public:student(string school_id = "12345", int num = 666, string name = "wangwu", int age = 18, string sex = "male"): _school_id(school_id), _num(1), _name(name), person(num, name, sex, age){}void func(int x){cout << "student::func()" << endl;}student(const student& st):_school_id(st._school_id), _num(st._num), _name(st._name), person(st)//拷贝构造同样需要对person单独进行拷贝/构造,如果是进行拷贝的话,可以像上面这样使用"切片",编译器自动把st中person的部分拷贝过来{cout << person::_num << endl;}protected:string _school_id;int _num;
public:string _name;
};int main()
{student st("778899", 444, "oldking");student st1(st);return 0;
}//输出: 444
  • 如果不单独对person进行拷贝的话,就会调用person的默认构造函数
class person
{
public:person(int num = 777, string name = "zhangsan", string sex = "male", int age = 18): _num(num), _name(name), _sex(sex), _age(age){}void func(){cout << "person::func()" << endl;}person(const person& p): _num(p._num), _name(p._name), _sex(p._sex), _age(p._age){}protected:int _num;string _sex;int _age;public:string _name;
};class student : public person
{
public:student(string school_id = "12345", int num = 666, string name = "wangwu", int age = 18, string sex = "male"): _school_id(school_id), _num(1), _name(name), person(num, name, sex, age){}void func(int x){cout << "student::func()" << endl;}student(const student& st):_school_id(st._school_id), _num(st._num), _name(st._name){cout << person::_num << endl;}protected:string _school_id;int _num;
public:string _name;
};int main()
{student st("778899", 444, "oldking");student st1(st);return 0;
}//输出: 777
14.5.3 关于赋值重载
class person
{
public:person(int num = 777, string name = "zhangsan", string sex = "male", int age = 18): _num(num), _name(name), _sex(sex), _age(age){}void func(){cout << "person::func()" << endl;}person(const person& p): _num(p._num), _name(p._name), _sex(p._sex), _age(p._age){}person& operator=(const person& p){if (this != &p){_num = p._num;_sex = p._sex;_age = p._age;_name = p._name;}}protected:int _num;string _sex;int _age;public:string _name;
};class student : public person
{
public:student(string school_id = "12345", int num = 666, string name = "wangwu", int age = 18, string sex = "male"): _school_id(school_id), _num(1), _name(name), person(num, name, sex, age){//cout << person::_num << endl;}void func(int x){cout << "student::func()" << endl;}student(const student& st):_school_id(st._school_id), _num(st._num), _name(st._name), person(st){cout << person::_num << endl;}student& operator=(const student& st){if (this != &st){//这里一定要指定类域,否则会因为构成隐藏而造成递归person::operator=(st);_school_id = st._school_id;_num = st._num;_name = st._name;}}protected:string _school_id;int _num;
public:string _name;
};
14.5.4 关于析构函数
class person
{
public:person(int num = 777, string name = "zhangsan", string sex = "male", int age = 18): _num(num), _name(name), _sex(sex), _age(age){}void func(){cout << "person::func()" << endl;}person(const person& p): _num(p._num), _name(p._name), _sex(p._sex), _age(p._age){}person& operator=(const person& p){if (this != &p){_num = p._num;_sex = p._sex;_age = p._age;_name = p._name;}}~person(){}protected:int _num;string _sex;int _age;public:string _name;
};class student : public person
{
public:student(string school_id = "12345", int num = 666, string name = "wangwu", int age = 18, string sex = "male"): _school_id(school_id), _num(1), _name(name), person(num, name, sex, age){//cout << person::_num << endl;}void func(int x){cout << "student::func()" << endl;}student(const student& st):_school_id(st._school_id), _num(st._num), _name(st._name), person(st){cout << person::_num << endl;}student& operator=(const student& st){if (this != &st){person::operator=(st);_school_id = st._school_id;_num = st._num;_name = st._name;}}//子类的析构会自动调用父类的析构,我们不需要管父类//这是因为父类先被创建,子类后被创建,为了保证先析构子类再析构父类做出的规定//(并且,假设我们在子类的析构显式调用父类的析构,还是需要指定类域,因为编译器默认将析构的名字统一规定成了destructor,两个析构构成隐藏)~student(){}protected:string _school_id;int _num;
public:string _name;
};int main()
{student st("778899", 444, "oldking");student st1(st);return 0;
}
14.6 不能被继承的类
  • 如果一个类的默认构造函数被标记为private,因为子类实例化的时候需要调用父类的默认构造函数,但因为private的原因其默认构造函数在子类不可见,所以在实例化的时候会导致报错
class Person
{
protected:string _name;int _age;private:Person():_name("oldking"), _age(18){}
};

请添加图片描述

  • CPP11之后,可能是觉得这样的方式不够明显,且子类定义了不会报错,还要到实例化的时候才会报错,就很麻烦,所以新增了关键字final
class Person final
{
public:Person():_name("oldking"), _age(18){}protected:string _name;int _age;
};

请添加图片描述

14.7 继承与友元
  • 友元关系不会被继承,只会保留在父类,被标记的友元函数有访问子类中父类的那部分中的私有/保护成员的权限
//声明类型 
class Student;class Person
{
public:friend void func(const Person& p, const Student& st);Person():_name("oldking"), _age(18){}protected:string _name;int _age;
};class Student : public Person
{
public:Student():_id_number("8877665544"){}protected:string _id_number;
};void func(const Person& p, const Student& st)
{cout << p._age << endl;cout << st._age << endl;//下面这行使用会报错//cout << st._id_number << endl;
}int main()
{Person p;Student st;func(st, st);return 0;
}//输出:18
//     18

请添加图片描述

14.8 继承与静态成员
  • 在继承中,静态成员实际只存在一份,由子类和父类共享
class Person
{
public:Person():_name("oldking"), _age(18){}static string _sex;protected:string _name;int _age;
};string Person::_sex = "woman";class Student : public Person
{
protected:string _id_number;
};int main()
{Person p;Student st;cout << Person::_sex << endl;cout << Student::_sex << endl;cout << p._sex << endl;cout << st._sex << endl;return 0;
}

请添加图片描述

14.9 继承模型
14.9.1 单继承
  • 简单来说单继承就是只有一个"继承链"的继承方式,类似于链表,每个类的父节点都是唯一的

  • 类似于 person->student->monitor(班长)

14.9.2 多继承
  • 多继承就相对来讲复杂一些,多继承的出现是为了更好地模拟/描述现实世界,因为现实世界往往是复杂的,各种对象间都存在继承关系,类似于电子产品中的笔记本电脑和手机,它们都属于移动计算机的一种,他们都是移动计算机的子类,但有一个子类同时继承了笔记本电脑和手机,即平板电脑,同时具备有手机和电脑的特性
class Computer
{
protected:string _cpu;string _screen;//...
};class Phone : public Computer
{
protected:string _touch_panel; //触控屏//...
};class Laptop : public Computer
{
protected:string _touch_pad; //触控板//...
};class Pad : public Phone, public Laptop
{
};
  • CPP支持多继承,但事实上多继承其实是CPP的一个大坑,像是Java就直接禁用了多继承

  • 这个多继承坑就坑在,他会产生菱形继承,咱来先看看什么是菱形继承

  • 比方说,刚刚我们举的平板电脑的例子就是经典的菱形继承
    请添加图片描述

  • 我们来分析一下菱形继承会导致什么问题

  • 计算机:

    • 计算机的特性
  • 笔记本电脑:

    • 计算机的特性
    • 笔记本额外有的特性
  • 手机:

    • 计算机的特性
    • 手机额外有的特性
  • 平板电脑:

    • 计算机的特性
    • 计算机的特性
    • 手机额外有的特性
    • 笔记本额外有的特性
  • 发现了吗,平板电脑因为既继承了笔记本电脑,又继承了手机,所以其中包含了两个计算机的特性,这就产生了数据冗余和二义性的问题

  • 数据冗余:多了一份重复的数据,空间上会有浪费

  • 二义性,如果我们想访问的数据是重复的那部分数据,编译器就不知道应该访问哪一份的

请添加图片描述

  • 以下是正确使用方式
class Pad : public Phone, public Laptop
{
public:void func(){cout << Phone::_cpu << endl;}
};
  • 总的来说,多继承最好别用,非常容易搞混,菱形继承千万别用,弊大于利,极不推荐用,能不用就不用
14.9.3 虚继承
  • 回到上面的例子,如果我实在想用菱形继承怎么办,我们可以加上虚继承

  • 虚继承可以理解为是一个标记,虚继承会标记当前类中的父类,如果当前类的子类是多继承就会影响到子类,将当前类的子类中重复的当前类的父类部分合二为一,所以说虚继承关系到3个具有父子关系的类

class Computer
{
protected:string _cpu;string _screen;//...
};class Phone : virtual public Computer
{
protected:string _touch_panel; //触控屏//...
};class Laptop : virtual public Computer
{
protected:string _touch_pad; //触控板//...
};class Pad : public Phone, public Laptop
{
public:void func(){cout << &_cpu << endl;cout << &(Phone::_cpu) << endl;cout << &(Laptop::_cpu) << endl;}
};int main()
{Pad p;p.func();return 0;
}
  • 可以看到实际在类平板电脑中只创建了一个计算机类
    请添加图片描述

  • 实际开发中的思路(可能?)是这样的

    1. 定义了类计算机,然后从计算机继承下来了手机和笔记本电脑
    2. 考虑到手机和平板电脑可能会作为多继承的父类
    3. 思考到如果作为多继承的父类的话可能会造成类计算机重复存在,会产生数据冗余和二义性
    4. 于是将手机和平板电脑的继承方式改为虚继承
  • 当然,报错了再加virtual也行

  • 假设有以下这种情况

请添加图片描述

  • 此时,重复的数据应该是计算机的这部分数据,所以计算机向笔记本电脑和手机的继承方式应该是虚继承,标记"笔记本电脑"中的"计算机"和"手机"中的"计算机",实际对Windows平板电脑没有影响,影响的是Win掌机
14.9.4 多继承下的子/父类地址关系
  • 我们简单看一看以下代码
class A
{
protected:int _a;
};class B
{
protected:int _b;
};class C : public A, public B
{
protected:int _c;
};int main()
{C c;A* pa = &c;B* pb = &c;C* pc = &c;cout << pa << endl;cout << pb << endl;cout << pc << endl;return 0;
}
  • pc指向的一定是c的起始地址这毋庸置疑,但papb指向哪里这是有讲究的

  • c中,我们知道父类相当于作为一个独立的对象去存放,构造c真正前,首先要对父类进行构造,于是我们能看到pa指向的位置和pc相同,其实是因为A优先被构造,后面构造的是B,于是我们能看到B紧接着就在A后面

请添加图片描述

  • 所以说,在多继承中,父类会优先被构造且放在当前类的最前面
14.10 继承与组合
14.10.1 黑箱与白箱
  • 黑箱:简单来说,黑箱就是封装好各种设计细节,只保留关键接口给使用者,使用者无需关心底层的设计细节,拿来就用,比方说我们设计一个my_Stack,调用了stl提供的list来实现,我们压根就不需要关心这个链表具体是什么类型,只管用就完事了,我们只需要知道,用它提供的接口可以完成my_Stack的封装,封装完之后依旧仅外露一部分接口,保持黑箱
  • 白箱:白箱就是各种底层细节全部展现给使用者,使用者根据自己的使用情况,想怎么调用就可以怎么调用,甚至能对底层细节进行深度修改
14.10.2 黑箱与白箱的优劣
  • 黑箱:

    • 因为不会暴露底层细节,使用者也不会修改和使用底层细节,所以如果想要修改黑箱其中的细节,使用者无需更改代码,实现的效果依旧不变
  • 白箱:

    • 白箱因为暴露了底层细节,使用者也可以随意调用,就会导致如果对白箱的底层细节做出了修改,因为使用者使用了底层的内容,导致使用者也需要对代码进行修改,是一件非常得不偿失的事
14.10.3 has-a & is-a
  • 两个类的关系可以用has-ais-a来表达

  • has-a:即包含关系,我们可以说一台宝马汽车有4个轮子,这四个轮子就可以作为自定义类放进宝马汽车中

  • is-a:即继承关系,我们可以说宝马汽车是一台车,继承自一台车,但不能说宝马里有个车对吧

14.10.4 继承&组合与黑箱&白箱
  • 不难看出,继承应该对应着白箱,因为父类一般不会设计private标签,所有的底层全都是开放的,导致子类可以很轻松地使用到父类底层的所有东西

  • 而组合就是将一到多个自定义类封装到当前这个大类中,你看不到这几个类的实现细节,只管用就完事了,也就对应着黑箱

  • 所以说,一般来说,如果两个类的关系可以用has-a来表达,就尽量用has-a来表达,尽可能用组合描述事物,除非这个事物用继承来描述更加合适

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/428111.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JS实现树形结构数据中特定节点及其子节点显示属性设置的技巧(可用于树形节点过滤筛选)

大家好&#xff0c;今天我要分享的是如何在树形结构的数据中&#xff0c;根据特定条件设置节点及其所有子节点的显示属性。在实际项目中&#xff0c;这种需求非常常见&#xff0c;特别是在需要动态展示和隐藏节点的情况下。下面我将通过一个具体的示例来讲解实现过程。 需求分析…

有关C# .NET Core 过滤器的使用

想用一个过滤器实现特定接口的审核日志记录&#xff0c;结果报了错&#xff0c;看了看感觉有些基础要补&#xff0c;所以想记录下来 错误&#xff1a; 在属性过滤器中使用了依赖注入&#xff0c;结果在应用在控制层接口时报了传参的错 //过滤器 public class AuditRecordFil…

tcpdump使用方法

一、centos上可以采用下面的命令进行安装。 yum install tcpdump 二、实例&#xff1a; 1、监视指定网络接口的数据包 即监听指定网卡的数据包&#xff0c;若不指定网卡&#xff0c;默认tcpdump只会监视第一个网络接口。如监听 eth0网卡&#xff0c;如下&#xff1a; tcpd…

Double-Fetch漏洞检测工具的部署、使用与原理分析

文章目录 前言1、概述1.1、简介1.2、工作原理1.2.1、内核空间与用户空间的信息传递1.2.2、Double-Fetch漏洞产生的原因1.2.3、产生Double-Fetch漏洞的情况1.2.4、一个Double-Fetch漏洞示例1.2.5、Double-Fetch漏洞检测工具原理 1.3、模式匹配原理分析1.3.1、Coccinelle介绍1.3.…

大厂程序员的健身之路

大厂程序员的健身之路 基本信息饮食正餐营养补剂 睡眠训练计划 基本信息 健身时间&#xff1a;2023.03 -> 2024.09体重变化&#xff1a;52kg -> 67kg 饮食 正餐 早餐&#xff1a;不吃午餐&#xff1a;两碗米饭 鱼/鸡肉 蔬菜 酸奶晚餐&#xff1a;两碗米饭 鱼/鸡肉…

java之杨辉三角问题

给定一个非负整数 numRows&#xff0c;生成「杨辉三角」的前 numRows 行。 在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。 如何实现呢&#xff1f; 思路&#xff1a;首先&#xff0c;我们可以将杨辉三角视作i行j列的二维数组。除了第一行和第二行之外&am…

BuripSuiteProfessional 抓取HTTPS配置

1.电脑拿开代理 谷歌为例 点击三点-设置 -输入代理--点击代理设置 打开手动代理---IP ,端口如图-点击保存 2.下载CA证书 打开代理后,谷歌浏览器打开,输入/burp--如下图-点击CA证书下载证书 选择下载目录--桌面 3.安装CA证书 谷歌浏览器中点开设置-输入证书-点击安全 点击…

传知代码-多示例AI模型实现病理图像分类

代码以及视频讲解 本文所涉及所有资源均在传知代码平台可获取 概述 本文将基于多示例深度学习EPLA模型实现对乳腺癌数据集BreaKHis_v1的分类。EPLA模型是处理组织病理学图像的经典之作。EPLA模型是基于多示例学习来进行了&#xff0c;那么多示例学习模型对处理病理学图像具有…

优化算法(一)—遗传算法(Genetic Algorithm)附MATLAB程序

遗传算法&#xff08;Genetic Algorithm, GA&#xff09;是一种启发式搜索算法&#xff0c;用于寻找复杂优化问题的近似解。它模拟了自然选择和遗传学中的进化过程&#xff0c;主要用于解决那些传统算法难以处理的问题。 遗传算法的基本步骤&#xff1a; 初始化种群&#xff0…

GNN-RAG:用于大模型推理的图神经检索

GNN-RAG&#xff1a;用于大模型推理的图神经检索 秒懂大纲提出背景解法拆解全流程优化创意总结 论文&#xff1a;GNN-RAG: Graph Neural Retrieval for Large Language Model Reasoning 代码&#xff1a;https://github.com/cmavro/GNN-RAG 秒懂大纲 ├── GNN-RAG【主题】…

美国站群服务器优化技巧解析

美国站群服务器&#xff0c;作为专为管理多个网站而设计的托管解决方案&#xff0c;其优化对于提升网站性能和用户体验至关重要。以下是一些关键的优化技巧&#xff1a; 首先&#xff0c;硬件配置是基础。选择高性能的CPU、大容量的内存以及高速的硬盘(如SSD)是提升服务器运算速…

Java 集合详解

目录 一. 概述 二. Collection接口实现类 三. Map接口实现类 四. 线程安全集合 五. List接口下集合实现原理 1. ArrayList实现原理 1.1. 基于动态数组 1.2. 随机访问 1.3. 添加元素 1.4. 删除元素 1.5. 迭代器 1.6. 克隆和序列化 1.7. ArrayList简单使用 2. Link…

Linux环境变量进程地址空间

目录 一、初步认识环境变量 1.1常见的环境变量 1.2环境变量的基本概念 二、命令行参数 2.1通过命令行参数获取环境变量 2.2本地变量和内建命令 2.3环境变量的获取 三、进程地址空间 3.1进程&#xff08;虚拟&#xff09;地址空间的引入 3.2进程地址空间的布局和理解 …

11年计算机考研408-数据结构

设执行了k次。 解析&#xff1a; d要第一个出&#xff0c;那么abc先入栈&#xff0c;d入栈然后再出栈&#xff0c;这前面是一个固定的流程&#xff0c;后面就很灵活了&#xff0c;可以ecba&#xff0c;ceba&#xff0c;cbea&#xff0c;cbae。 答案是4个序列。 解析&#xff1a…

【论文阅读】PERCEIVER-ACTOR: A Multi-Task Transformer for Robotic Manipulation

Abstract transformers凭借其对大型数据集的扩展能力&#xff0c;彻底改变了视觉和自然语言处理。但在机器人操作中&#xff0c;数据既有限又昂贵。通过正确的问题表述&#xff0c;操纵仍然可以从变形金刚中受益吗&#xff1f;我们使用peract来研究这个问题&#xff0c;peract…

Spring Boot利用dag加速Spring beans初始化

1.什么是Dag&#xff1f; 有向无环图(Directed Acyclic Graph)&#xff0c;简称DAG&#xff0c;是一种有向图&#xff0c;其中没有从节点出发经过若干条边后再回到该节点的路径。换句话说&#xff0c;DAG中不存在环路。这种数据结构常用于表示并解决具有依赖关系的问题。 DAG的…

elasticsearch同步mysql方案

文章目录 1、1. 使用数据库触发器2. 使用定时任务3. 监听MySQL二进制日志&#xff08;binlog&#xff09;4. 使用数据管道5. 使用第三方工具或服务6. 编写自定义脚本注意事项 2、1. 使用Logstash步骤&#xff1a;示例配置&#xff1a; 2. 使用Debezium步骤&#xff1a; 3. 自定…

【Redis入门到精通三】Redis核心数据类型(List,Set)详解

目录 Redis数据类型 ​编辑 1.List类型 &#xff08;1&#xff09;常见命令 &#xff08;2&#xff09;内部编码 2.Set类型 &#xff08;1&#xff09;常见命令 &#xff08;2&#xff09;内部编码 Redis数据类型 查阅Redis官方文档可知&#xff0c;Redis提供给用户的核…

JavaScript - Document文档操作

1. 前言 ​​​​​​​ 编写网页时&#xff0c;我们需要时刻操作文档进而完成我们想要的效果。这就是通过文档对象模型实现&#xff0c;使用Document对象控制HTML以及样式信息的API 2. Document的树结构 在了解Document文档对象模型之前&#xff0c;我们先了解Dom的树结构 …

使用scp命令从本地往服务器传输文件失败

解决办法&#xff1a; 找到这个文件&#xff0c;打开&#xff0c;将里面的服务器ip对应的一行数据删掉即可。