【C++面向对象程序设计】CH5 继承与派生(续)——虚基类

news2025/1/12 12:28:59

目录

前言

一、虚基类的作用

二、虚基类的初始化

三、例【5.9】在【例5.8】中在teacher类和student类之上增加一个共同的基类person,人员的一些基本数据放在person中

四、多层多重继承用虚基类

五、虚基类的构造函数

六、多重继承如何工作

七、虚拟继承

八、虚拟继承沙发床

九、多继承的构造顺序 

十、多重继承的构造函数举例

十一、多重继承综合举例

1.方法一

(1)代码一 

(2)结果一 

2.方法二

(1)代码二 

(2)结果二 

3.方法三

(1)代码三

(2)结果三 


前言

        从上面的例子可知,如果一个派生类有多个直接基类,而这些直接基类有有一个共同的基类,在派生类中会保留这个间接共同基类数据成员的多个同名成员。图5.19和图5.20描述了这种情况。在引用这些同名成员时,为避免二义性,必须在派生类对象名后增加直接基类名。如:

c1.A::a=3; c1.A::display();

一、虚基类的作用

        如果不希望在派生类中保留间接共同基类的多个同名成员,C++提供了虚基类的方法,使派生类在继承间接共同基类时只保留一份成员。

        虚基类:用于有共同基类的场合。

        声明:以virtual修饰说明基类。(class B1:virtual public B)

        作用:主要用来解决多层继承时可能发生的对同一基类继承多次而产生的二义性问题;为最底层的派生类提供唯一的基类成员,而不重复产生多次拷贝。

        注意:在第一级继承时就要将共同基类设计为虚基类。

        声明虚基类的格式:

class  派生类名:virtual 继承方式  基类名

        当基类通过多条派生路径被一个派生类继承时,派生类只继承该基类一次。

        现将A类声明为虚基类:

class  A
{… … };
class  B: virtual public A
{… … };
class  C: virtual public A
{… … };

        虚基类是在声明派生类时,指定继承方式时声明的。因为一个基类可以作为一个派生类的虚基类,同时也可以作为另一个派生类的非虚基类。

        派生类B和C声明虚基类后,派生类D的成员如图5.23所示。

二、虚基类的初始化

        如果在虚基类中定义了带参数的构造函数,而且没定义默认构造函数,要求在它的所有派生类(直接和间接)中,通过构造函数的初始化表对虚基类进行初始化。 

class  A
{ A (int k) { } … … };

class  B: virtual public A
{B (int n ):A(n){ }… … };

class  C: virtual public A
{C (int n ):A(n){ } … … };

class  D: public B,public C
{D (int n ):A(n),B(n),C(n) { } … … };

【注】

        在定义类D的构造函数时,与以往的方法不同。虚基类在派生类中只有一份数据成员,所以这份数据成员的初始化必须由派生类直接给出。如果不由最后的派生类(如图5.21的类D)直接对虚基类初始化,而由虚基类的直接派生类(如图5.21的类B和类C)对虚基类初始化,就有可能由于在类B和类C的构造函数中对虚基类给出不同的初始化参数。所以规定:最后的派生类不仅要负责对其直接基类初始化,还要负责对虚基类初始化。

        可能有人提出:类D的构造函数用初始化表调用了虚基类的构造函数A,类B和类C的构造函数也用初始化表调用了虚基类的构造函数A,这岂不是调用了三次虚基类构造函数?其实C++编译系统只执行最后的派生类调用虚基类的构造函数,忽略虚基类其他派生类(如类B和类C)调用虚基类构造函数,保证对虚基类的数据成员只作一次初始化。

三、例【5.9】在【例5.8】中在teacher类和student类之上增加一个共同的基类person,人员的一些基本数据放在person中

#include <iostream>
#include <string.h>
using namespace std;

class Person 
{
	public:
		Person(char *nam, char s, int a) 
		{ //    构造函数
			strcpy(name, nam);
			sex = s;
			age = a;
		}
	protected:                                    //    保护成员
		char name[20];
		char sex;
		int age;
};

class Teacher: virtual public Person 
{ //声明Person为公用继承的虚基类
	public:
		Teacher(char *nam, char s, int a, char *t): Person(nam, s, a) 
		{ //构造函数
			strcpy(title, t);
		}
	protected:                                       //    保护成员
		char title[10];                                //    职称
};

class Student: virtual public Person
//声明Person为公用继承的虚基类
{
	public:
		Student(char *nam, char s, int a, float sco):
			Person(nam, s, a), score(sco) { } //    初始化表
	protected:                                      //    保护成员
		float score;                                  //    成绩
};

class Graduate: public Teacher, public Student
//    声明Teacher和Student类为公用继承的直接基类
{
	public:
		Graduate(char *nam, char s, int a, char *t, float sco, float w): //  构造函数
			Person(nam, s, a), Teacher(nam, s, a, t), Student(nam, s, a, sco),
			wage(w) {} 
        void show( ) 
        {                               //    输出研究生的有关数据
			cout << "name:" << name << endl;
			cout << "age:" << age << endl;
			cout << "sex:" << sex << endl;
			cout << "score:" << score << endl;
			cout << "title:" << title << endl;
			cout << "wages:" << wage << endl;
		}
	private:
		float wage;                     //工资
};

int main( ) 
{
	Graduate grad1("Wang-li", 'f', 24, "assistant", 89.5, 1234.5);
	grad1.show( );
	return 0;
}

四、多层多重继承用虚基类

#include <iostream>
#include <string.h>
using namespace std;

class B 
{
	public:
		B(int i ) 
		{
			b = i;
		}
		int b;
};

class B1 : virtual public B 
{ //  在第一层声明虚基类
	public:
		B1(int b, int bx): B(b) 
		{ //  在每层派生中都调用基类
			b1 = bx;
		}
	private:
		int b1;
};

class B2 : virtual public B 
{    //  在第一层声明虚基类
	public:
		B2(int b, int bx): B(b) 
		{ //  在每层派生中都调用基类
			b2 = bx;
		}
	private:
		int b2;
};

class C: public B1, public B2 
{
	public: //  在每层派生中都调用基类构造函数
		C(int x1, int x2, int x3, int x4): B(x1), B1(x1, x2), B2(x1, x3) {
			d = x4;
		}
	private:
		int d;
};

int main(int argc, char *argv[]) 
{
	C cc(1, 2, 3, 4);
	cout << cc.b << endl;
	return 0;
}

五、虚基类的构造函数

        调用顺序的规则:

  • 若同一层次中只包含多个虚基类,按他们声明的先后次序调用,再调用派生类的构造函数
  • 若虚基类由非虚基类派生而来,先调用基类构造函数;再掉用派生类的构造函数
  • 若同一层次中同时包含虚基类和非虚基类,先调用虚基类的构造函数;再掉用非虚基类的构造函数;最后调用派生类构造函数

六、多重继承如何工作

        两用沙发是一张沙发,也是一张床,两用沙发允许同时继承沙发和床的特征,即SleepSofa继承Bed和Sofa两个类。

        在上节中,sofa和bed都有一个weight成员这是合理的,因为两者都是实体,都有重量。问题是SleepSofa继承哪个重量?回答是两者都继承,由于两者有相同的个名字weight,使得对weight的使用变得稍微复杂一点。

        假如按照下面的使用:

int  main()
{    
    SleeperSofa ss;
    ss.Setweight(20); 
    … 
}

        结果导致名称冲突(name collision),编译时出错。解决的方法是在成员名前指定其基类名:

int  main()
{    
    SleeperSofa ss;
    ss.sofa.Setweight(20);  
    … 
}

         在编写应用程序时,还要程序员知道类的层次信息,增加了编程的复杂度,在单继承中不会出现这样的问题。

七、虚拟继承

        客观上讲,一个SleepSofa没有沙发和床两种重量,如此继承不是真实世界的反应。其实沙发和床都是家居的一种,凡是家具都有重量,所以通过分解考虑它们的关系。

        因为SleepSofa不是直接继承Furniture,而是bed和sofa各自继承Furniture,所以完整的SleepSofa对象的内存布局如前面的图,它包括一个完整的bed,还有一个完整的sofa和SleepSofa自己的成员。它包括了两个weight成员,C++不知道SetWeight()属于哪个Furniture成员,指向Furniture的指针也不知道究竟指向哪个Furniture,这就是程序多重继承2无法通过编译的原因。

        SleepSofa只需要一个Furniture,所以希望它只包含一个Furniture拷贝,同时又要共享bed和sofa的成员函数和数据成员,C++提供了虚拟继承方法实现这种继承结构。

        在定义bed和sofa继承Furniture时,在冒号和继承方式之间增加关键字virtual。这相当说,如果还没有Furniture,则加入一个Furniture拷贝,否则就用已有的那下一个。此时一个SleepSofa对象在内存中只保留一个Furniture拷贝。

【注】虚拟继承的虚拟和虚拟函数的虚拟没有任何关系

八、虚拟继承沙发床

#include <iostream>
#include <string.h>
using namespace std;

class Furniture 
{
	protected:
		int weight ;
	public:
		Furniture() {}
		void Setweight( int i ) 
		{
			weight = i ;
		}
		int getweight() 
		{
			return weight;
		}
};

class bed: virtual public Furniture 
{
	public:
		bed() {}
		void Sleep() 
		{
			cout << "  睡眠 " << endl;
		}

};

class sofa: virtual public Furniture 
{

	public:
		sofa() {}
		void WatchTV() 
		{
			cout << "  看电视  " << endl;
		}

};

class SleeperSofa : public bed, public sofa 
{
	public:
		SleeperSofa() {}
		void Foldout() 
		{
			cout << "  打开沙发" << endl;
		}
};

int main(int argc, char *argv[]) 
{
	SleeperSofa ss;
	ss.Setweight(20);
	Furniture *pf;
	pf = &ss;
	cout << pf-> getweight() << endl;
	cout << ss.getweight() << endl;
	return 0;
}

九、多继承的构造顺序 

        构造函数按下列顺序被调用:

  • 按继承虚基类的顺序调用调用虚基类的构造函数
  • 按继承非虚基类的顺序调用非虚基类的构造函数
  • 按声明成员对象的顺序调用其构造函数
  • 调用派生类自己的构造函数

十、多重继承的构造函数举例

#include <iostream>
#include <string.h>
using namespace std;

class OBJ1 
{
	public:
		OBJ1() 
		{
			cout << "调用OBJ1类构造函数" << endl;
		}
};

class OBJ2 
{
	public:
		OBJ2() 
		{
			cout << "调用OBJ2类构造函数" << endl;
		}
};

class Base1 
{
	public:
		Base1() 
		{
			cout << "调用Base1类构造函数" << endl;
		}
};

class Base2 
{
	public:
		Base2() 
		{
			cout << "调用Base2类构造函数" << endl;
		}
};

class Base3 
{
	public:
		Base3() 
		{
			cout << "调用Base3类构造函数" << endl;
		}
};

class Base4 
{
	public:
		Base4() 
		{
			cout << "调用Base4类构造函数" << endl;
		}
};

class Derived: public Base1, virtual public Base2,public Base3, virtual public Base4 
{
	public:
		Derived(): Base4(), Base3(), Base2(), Base1(), obj1(), obj2() 
		{
			cout << "调用派生类构造函数成功!" << endl;
		}
	protected:
		OBJ1 obj1;
		OBJ2 obj2;
};

int main(int argc, char *argv[]) 
{
	Derived aa;
	cout << "派生类对象 aa 构造成功,谢谢! " << endl;
	return 0;
}

十一、多重继承综合举例

        分别定义Teacher类和Cadre类,用多重继承方式由这两个类派生出新类Teacher_Cadre。

  • 在这两个基类中都包含数据成员:姓名、年龄、性别、地址、电话
  • 在Teacher类中还有职称,在Cadre类中还有职务,在派生类中有工资数据成员
  • 两个基类中的数据成员用相同的名字,在引用时指定作用域
  • 在类体中声明成员函数,在类体外定义成员函数
  • 在派生类的成员函数show中调用Teache类的display函数,输出姓名、年龄性别、职称、地址、电话,然后再用cout语句输出职务和工资

1.方法一

(1)代码一 

#include <iostream>
#include <string.h>
using namespace std;

class Teacher 
{
	protected:
		string name;
		int age;
		char sex;
		string title;
		string addr;
		string tel;
	public:
		Teacher(string nam, int a, char s, string tit, string ad, string t);
		void display();
};

Teacher::Teacher(string nam, int a, char s, 
	string tit, string ad, string t): name(nam), 
	age(a),  sex(s), title(tit),addr(ad), tel(t) { }

void Teacher::display() 
{
	cout << "name:" << name << endl;
	cout << "age" << age << endl;
	cout << "sex:" << sex << endl;
	cout << "title:" << title << endl;
	cout << "address:" << addr << endl;
	cout << "tel:" << tel << endl;
}

class Cadre 
{
	protected:
		string name;
		int age;
		char sex;
		string post;
		string addr;
		string tel;
	public:
		Cadre(string nam, int a, char s, string p, string ad, string t);
		void display();
};

Cadre::Cadre(string nam, int a, char s, 
	string p, string ad, string t):name(nam), 
	age(a), sex(s), post(p), addr(ad), tel(t) {}

void Cadre::display() 
{
	cout << "name:" << name << endl;
	cout << "age:" << age << endl;
	cout << "sex:" << sex << endl;
	cout << "post:" << post << endl;
	cout << "address:" << addr << endl;
	cout << "tel:" << tel << endl;
}

class Teacher_Cadre: public Teacher, public Cadre 
{
	private:
		float wage;
	public:
		Teacher_Cadre(string nam, int a, char s, string tit, string p, string ad, string t, float w);
		void show( );
};

//派生类构造函数
Teacher_Cadre::Teacher_Cadre(string nam, 
	int a, char s, string t, string p, string ad, 
	string tel,float w):  Teacher(nam, a, s, t, ad, tel), 
	Cadre(nam, a, s, p, ad, tel), wage(w) {}

void Teacher_Cadre::show( ) 
{
	Teacher::display();
	cout << "post:" << Cadre::post << endl;
	cout << "wages:" << wage << endl;
}

int main(int argc, char *argv[]) 
{
	Teacher_Cadre t1("Wang-li", 50, 'f', 
	"prof.", "president", "135 Beijing Road,Shanghai", 
	"(021)61234567", 1534.5);
	t1.show( );
	cout << "基类Teacher长度是:" << sizeof( Teacher) << "字节" << endl;
	cout << "基类Cadre长度是:" << sizeof( Cadre) << "字节" << endl;
	cout << "派生类对象长度是:" << sizeof( t1) << "字节" << endl;
	return 0;
}

(2)结果一 

        从程序运行结果得知,不采用虚基类,派生类的对象长度是各个基类长度之和。这对提高内存利用率不利。我们用虚基类的方法求解上面的题目,看派生类对象的长度怎样变化。

2.方法二

(1)代码二 

#include <iostream>
#include <string.h>
using namespace std;

class Teacher 
{
	protected:
		string name;
		int age;
		char sex;
		string title;
		string addr;
		string tel;
	public:
		Teacher(string nam, int a, 
			char s, string tit, string ad, string t);
		void display();
};

Teacher::Teacher(string nam, int a, char s,
    string tit, string ad, string t): name(nam),
	age(a),  sex(s), title(tit), addr(ad), tel(t) { }

void Teacher::display() 
{
	cout << "name:" << name << endl;
	cout << "age" << age << endl;
	cout << "sex:" << sex << endl;
	cout << "title:" << title << endl;
	cout << "address:" << addr << endl;
	cout << "tel:" << tel << endl;
}

class Cadre 
{
	protected:
		string name;
		int age;
		char sex;
		string post;
		string addr;
		string tel;
	public:
		Cadre(string nam, int a, char s, 
			string p, string ad, string t);
		void display1();
};

Cadre::Cadre(string nam, int a, char s, 
	string p, string ad, string t):
	name(nam), age(a), sex(s), post(p), 
	addr(ad), tel(t) {}

void Cadre::display1() 
{
	cout << "name:" << name << endl;
	cout << "age:" << age << endl;
	cout << "sex:" << sex << endl;
	cout << "post:" << post << endl;
	cout << "address:" << addr << endl;
	cout << "tel:" << tel << endl;
}

class Teacher_Cadre: virtual public Teacher, virtual public Cadre 
{
	public:
		Teacher_Cadre(string nam, int a, 
			char s, string tit, string p, string ad,
			string t, float w);
		void show( );
	private:
		float wage;
};

Teacher_Cadre::Teacher_Cadre(string nam, int a, 
	char s, string t, string p, string ad, string tel, float w):
	Teacher(nam, a, s, t, ad, tel), Cadre(nam, a, s, p, ad, tel), 
	wage(w) {}

void Teacher_Cadre::show( ) 
{
	//    Teacher::display();
	display();

	//    cout<<"post:"<<Cadre::post<<endl;
	cout << "post:" << post << endl;
	cout << "wages:" << wage << endl;
}

int main(int argc, char *argv[]) 
{
	Teacher_Cadre t1("Wang-li", 50, 'f', 
		"prof.", "president", "135 Beijing Road,Shanghai", 
		"(021)61234567", 1534.5);
	t1.show( );
	cout << "基类Teacher长度是:" << sizeof( Teacher) << "字节" << endl;
	cout << "基类Cadre长度是:" << sizeof( Cadre) << "字节" << endl;
	cout << "派生类对象长度是:" << sizeof( t1) << "字节" << endl;
	return 0;
}

(2)结果二 

        从程序运行结果得知,派生类对象的长度没有变小,而是变大。
        从教师类和干部类看到两个类有许多相同的数据成员,可以对两个类再抽象,建立一个基类staff,包括姓名、年龄、性别、地址、电话等数据成员。教师类从它派生,增加职称数据成员;干部类也从它派生,增加职务数据成员,教师干部类从教师类和干部类多重派生,增加工资成员。

3.方法三

(1)代码三

#include <iostream>
#include <string.h>
using namespace std;

class Staff 
{
	protected:
		string name;
		int age;
		char sex;
		string addr;
		string tel;
	public:
		Staff(string nam, int a, char s, string ad, string t);
		void display();

};

Staff::Staff(string nam, int a, char s, string ad, string t):
	name(nam), age(a), sex(s), addr(ad), tel(t) { }

void Staff::display() 
{
	cout << "name:" << name << endl;
	cout << "age" << age << endl;
	cout << "sex:" << sex << endl;
	cout << "address:" << addr << endl;
	cout << "tel:" << tel << endl;
}

class Teacher: virtual public Staff 
{
	protected:
		string title;
	public:
		Teacher(string nam, int a, char s, 
			string ad, string t, string tit);
		void display();

};

Teacher::Teacher(string nam, int a, char s, 
	string ad, string t, string tit):
	Staff(nam, a, s, ad, t), title(tit) { }

void Teacher::display() 
{
	Staff::display();
	cout << "title:" << title << endl;

}

class Cadre: virtual public Staff 
{
	protected:
		string post;
	public:
		Cadre(string nam, int a, 
			char s, string ad, string t, string pos);
		void display1();

};

Cadre::Cadre(string nam, int a, char s, 
	string ad, string t, string pos):
	Staff(nam, a, s, ad, t), post(pos) { }

void Cadre::display1() 
{
	Staff::display();
	cout << "post:" << post << endl;
}

class Teacher_Cadre:  public Teacher, public Cadre 
{
	public:
		Teacher_Cadre(string nam, int a, char s, 
			string tit, string p, string ad, string t, float w);
		void show( );
	private:
		float wage;
};

Teacher_Cadre::Teacher_Cadre(string nam, int a, char s, string t, 
	string p, string ad, string tel, float w):
	Staff( nam, a, s, ad, tel), Teacher(nam, a, s, ad, tel, t), 
	Cadre(nam, a, s, ad, tel, p), wage(w) {}

void Teacher_Cadre::show( ) 
{
	display();
	cout << "post:" << post << endl;
	cout << "wages:" << wage << endl;
}


int main(int argc, char *argv[]) 
{
	Teacher_Cadre t1("Wang-li", 50, 'f', "prof.", 
		"president", "135 Beijing Road,Shanghai", 
		"(021)61234567", 1534.5);
	t1.show( );
	cout << "基类Staff长度是:" << sizeof( Staff) << "字节" << endl;
	cout << "基类Teacher长度是:" << sizeof( Teacher) << "字节" << endl;
	cout << "基类Cadre长度是:" << sizeof( Cadre) << "字节" << endl;
	cout << "派生类教师干部对象t1长度是:" << sizeof( t1) << "字节" << endl;
	return 0;
}

(2)结果三 


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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【深入浅出Java并发编程指南】「难点 - 核心 - 遗漏」线程状态流转及生命周期的技术指南(知识点串烧)

前提介绍 本章主要介绍相关线程声明周期的转换机制以及声明周期的流转关系以及相关AQS的实现和相关的基本原理&#xff0c;配合这相关官方文档的中英文互译的介绍。 线程状态流转及生命周期 当线程被创建并启动以后&#xff0c;它既不是一启动就进入了执行状态&#xff0c;也不…

17. 电话号码的字母组合

17. 电话号码的字母组合 给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下&#xff08;与电话按键相同&#xff09;。注意 1 不对应任何字母。 示例 1&#xff1a; 输入&#xff1a;digits …

R语言分布滞后非线性模型(DLNM)研究发病率,死亡率和空气污染示例

全文下载链接&#xff1a;http://tecdat.cn/?p21317本文提供了运行分布滞后非线性模型的示例&#xff0c;同时描述了预测变量和结果之间的非线性和滞后效应&#xff0c;这种相互关系被定义为暴露-滞后-反应关联&#xff08;点击文末“阅读原文”获取完整代码数据&#xff09;。…

C语言文件操作

目录序言文件程序文件&数据文件程序文件数据文件文本文件&二进制文件文件名操作初阶打开&关闭文件fopen读写文件fputc & fgetc文件缓冲区文件指针操作进阶打开方式"w"(只写)"r"(只读)"a"(追加)文件的顺序读写fgets & fputsf…

Mac安装rabbitmq延迟队列插件

Mac安装rabbitmq延迟队列插件我是通过brew安装的rabbitmq&#xff0c;没有安装Homebrew的需要安装一下查看我们rabbitmq版本&#xff0c;我这里的版本是3.11.3&#xff0c;我们下载的插件大版本必须是3.11 brew info rabbitmq下载rabbitmq_delayed_message_exchange插件&#…

虹科分享 | 终端安全防护 | 网络安全术语列表(终篇)

如果你的工作或者生活与网络安全有关&#xff0c;你就知道它使用了自己独特的、不断发展的语言。术语和缩略语受到网络安全专家的喜爱。因此&#xff0c;我们创建了一个全面的网络安全词汇表&#xff0c;解释了常用的网络安全术语、短语和技术。我们设计此列表是为了揭开安全专…

春夏秋冬-第12届蓝桥杯Scratch选拔赛真题精选

[导读]&#xff1a;超平老师计划推出Scratch蓝桥杯真题解析100讲&#xff0c;这是超平老师解读Scratch蓝桥真题系列的第89讲。 蓝桥杯选拔赛每一届都要举行4~5次&#xff0c;和省赛、国赛相比&#xff0c;题目要简单不少&#xff0c;再加上篇幅有限&#xff0c;因此我精挑细选…

[附源码]计算机毕业设计springboot车险销售管理系统论文

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

MySQL软件常见操作

1登录MySQL 登录&#xff0c;如果你配置了环境变量就可以winr&#xff0c;在运行框输入cmd&#xff0c;输入登录命令 第一种&#xff1a;直接输入密码 mysql -uroot -p(你的密码没有有括号) 第二种不直接输入密码 mysql -uroot -p 前面两种都是localhost登录 下面是完整版 m…

流媒体传输 - RTSP 协议认证过程

Rtsp 认证 主要分为两种&#xff1a; 基本认证 &#xff08;Basic authentication&#xff09;和 摘要认证 &#xff08;Digest authentication&#xff09; 基本认证是 HTTP 1.0 提出的认证方案&#xff0c;其消息传输不经过加密转换因此存在严重的安全隐患。 摘要认证是 H…

[附源码]计算机毕业设计springboot房屋租赁信息系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Spring Boot 实现万能文件在线预览-开源学习一

Spring Boot 实现万能文件在线预览-开源学习一 1. 项目特性 支持word excel ppt&#xff0c;pdf等办公文档支持txt,java,php,py,md,js,css等所有纯文本支持zip,rar,jar,tar,gzip等压缩包支持jpg&#xff0c;jpeg&#xff0c;png&#xff0c;gif等图片预览&#xff08;翻转&am…

Linux信号基础

目录 一&#xff0c;信号的产生 1&#xff0c;终端按键 2&#xff0c;调用系统函数向进程发送信号 (1)、kill:给指定的进程发送指定的命令 (2)、raise:自己给自己发信号 ​(3)、abort&#xff1a;让当前进程收到信号异常终止 3,由硬件产生 (1)、比如除零错误&#xff0c…

Shiro框架

权限管理&#xff0c;一般指根据系统设置的安全规则或者安全策略&#xff0c;用户可以访问而且只能访问自己被授权的资源。权限管理几乎出现在任何系统里面&#xff0c;只要有用户和密码的系统。 很多人常将“用户身份认证”、“密码加密”、“系统管理”等概念与权限管理概念混…

Vue2 中使用“全局事件总线“实现任意组件间通信

前言&#xff1a; vue 中组件间通信的方式有很多 ------ 父传子propos&#xff0c;全局事件总线&#xff0c;消息订阅&#xff0c;vuex......等等&#xff0c;这篇文章带大家学习一下通过全局事件总线来实现任意组件间的通信。 文章目录&#xff1a; 一&#xff1a;什么是全局…

细节决定成败,Qlik数据洞察如何助力SEB化身“鹰眼”?

“随业务版图扩张&#xff0c;目前公司需要处理的数据集海量增长&#xff0c; SEB 的数据分析面临着越来越大的挑战&#xff0c;光是等待数据集计算的时间&#xff0c;都需要等待半天&#xff0c;效率低下导致我们很多工作都无法开展&#xff0c;我们需要一款更高效的 BI 工具”…

普元中间件Primeton AppServer6.5安装(Windows)

本文在Windows环境下安装普元中间件Primeton AppServer6.5&#xff08;以下简称PAS&#xff09; 一、安装前准备 1.1使用软件版本 Primeton_AppServer_6.5_Enterprise_Editio&#xff08;Windows&#xff09; 1.2安装前注意注意的点 1.需要提前安装JDK&#xff0c;并配置J…

神经网络和深度学习-加载数据集DataLoader

加载数据集DataLoader Dataloader的概念 dataloader的主要目标是拿出Mini-Batch这一组数据来进行训练 在处理多维特征输入这一文章中&#xff0c;使用diabetes这一数据集&#xff0c;在训练时我们使用的是所有的输入x&#xff0c;在梯度计算采用的是随机梯度下降&#xff08…

本地启动springboot项目失败端口问题

异常关键字&#xff1a; Cannot assign requested address: bind 排查结果 配置了环境变量【SERVER_ADDRESS】 网上搜了有的回答是端口占用&#xff0c;是不对的&#xff0c;端口占用的异常是这个【Web server failed to start. Port 8282 was already in use.】 排查结果…

麦芽糖-聚乙二醇-阿霉素maltose-Doxorubicin

麦芽糖-聚乙二醇-阿霉素maltose-Doxorubicin 中文名称&#xff1a;麦芽糖-阿霉素 英文名称&#xff1a;maltose-Doxorubicin 别称&#xff1a;阿霉素修饰麦芽糖&#xff0c;阿霉素-麦芽糖 还可以提供PEG接枝修饰麦芽糖&#xff0c;麦芽糖-聚乙二醇-阿霉素,Doxorubicin-PEG-…