【C++ 09】继承

news2024/12/30 4:27:22

文章目录

  • 🌈 一、继承的概念及定义
    • ⭐ 1. 继承的概念
    • ⭐ 2. 继承的定义
      • 🌙 2.1 定义格式
      • 🌙 2.2 继承方式和访问限定符
      • 🌙 2.3 继承父类成员访问方式的变化
      • 🌙 2.4 默认继承方式
  • 🌈 二、父类和子类对象赋值转换
    • ⭐ 1. 子类对象赋值给父类的 对象 / 指针 / 引用
  • 🌈 三、继承中的作用域
  • 🌈 四、子类的默认成员函数
    • ⭐ 1. 子类中如何生成默认成员函数
    • ⭐ 2. 编写子类的默认成员函数时的注意事项
  • 🌈 五、继承与友元
  • 🌈 六、继承与静态成员
  • 🌈 七、继承的方式
    • ⭐ 1. 单继承
    • ⭐ 2. 多继承
    • ⭐ 3. 菱形继承
  • 🌈 八、菱形虚拟继承
    • ⭐ 1. 虚拟继承格式
    • ⭐ 2. 虚拟继承样例
    • ⭐ 3. 虚拟继承位置
    • ⭐ 4. 虚拟继承原理
  • 🌈 九、继承笔试面试题

🌈 一、继承的概念及定义

⭐ 1. 继承的概念

  • 继承 (inheritance) 机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类。
  • 继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。以前我们接触的复用都是函数复用,继承是类设计层次的复用。
  • 小类可以继承大类的共有特性,让小类不需要再重复定义这些共有的内容,让小类只需要定义出自己所特有的东西即可。
    • 如:学生、老师、工人都可以继承人所共有的特性,猫、狗、老鼠也都可以继承动物所共有的特性。
  • 一般将被继承的类称为父类 / 基类。将继承父类的的类称为子类 / 派生类

举个例子

  • 人类都有自己的名字和年龄,那么学生类就可以继承这一共有的特性而不用重复定义。
  • 让学生类 student 和老师类 teacher 继承人类 person 的共有部分,让这两个子类定义独属于自己的学生 id 和教职工 id。
  • 继承后父类 person 的成员函数和成员变量就会变成子类的一部分。
class person
{
protected:
	string _name = "张三";
	int _age = 18;

public:
	void print()
	{
		cout << "name: " << _name << endl;
		cout << "age: " << _age << endl;
	}
};

// 学生类作为子类继承人类的成员变量和成员函数
class student : public person
{
protected:
	int _stuid;	// 学生 id
};

// 教师类作为子类继承人类的成员变量和成员函数
class teacher : public person
{
protected:
	int _jobid;	// 教师 id
};

int main()
{
	student s;
	teacher t;

	s.print();
	t.print();

	return 0;
}

image-20240908153019733

⭐ 2. 继承的定义

🌙 2.1 定义格式

  • 注意:在继承当中,父类也称为基类,子类是由基类派生而来的,所以子类又称为派生类。
class 子类名 : 继承方式 父类名
{
    // ......
};

🌙 2.2 继承方式和访问限定符

1. 继承方式

  1. public 继承
  2. protected 继承
  3. private 继承

2. 访问限定符

  1. public 访问
  2. protected 访问
  3. private 访问

🌙 2.3 继承父类成员访问方式的变化

  • 父类中被不同访问限定符修饰的成员,以不同的继承方式继承到子类当中后,该成员最终在子类当中的访问方式也会发生变化。
类成员 / 继承方式子类使用 public 方式继承子类使用 protected 方式继承子类使用 private 方式继承
父类的 public 成员变成子类的 public 成员变成子类的 protected 成员变成子类的 private 成员
父类的 protected 成员变成子类的 protected 成员变成子类的 protected 成员变成子类的 private 成员
父类的 private 成员在子类中不可见在子类中不可见在子类中不可见

1. 访问方式的变换规则

  • 种访问限定符的权限大小为:public > protected > private,父类成员访问方式的变化规则如下:
  1. 在父类当中的访问方式为 public 或 protected 的成员,在子类当中的访问方式变为:min(成员在父类的访问方式,继承方式)。
  2. 在父类中的访问方式为 private 的成员,在子类中都不可见。

2. 父类的 private 成员在子类中不可见

  • 无法在子类中访问父类的 private 成员。
  • 父类的 private 成员无论以什么方式被子类继承,子类对象都不能去访问这个 private 成员。
  • 注:实际上使用的一般都是 public 继承,几乎很少使用 protected 和 private 继承,也不提倡使用 protected 和 private 继承,因为使用 protected 和 private 继承下来的成员都只能在子类的类里面使用,实际中扩展维护性不强。

🌙 2.4 默认继承方式

  • 使用继承时也可以不指定继承方式,使用关键字 class 时默认继承方式是 private,而使用 struct 时默认继承方式是 public

举个栗子

  • 在关键字为 class 的子类中,所继承的父类成员的访问方式变为 private。
// 父类
class person
{
protected:
	string _name = "张三";
	int _age = 18;

public:
	void print()
	{
		cout << "name: " << _name << endl;
		cout << "age: " << _age << endl;
	}
};

// class 子类默认以 private 方式继承父类
class Student : person
{
protected:
	int _stuid;
};
  • 在关键字为 struct 的子类中,所继承的父类成员的访问方式变为 public。
// 父类
class person
{
protected:
	string _name = "张三";
	int _age = 18;

public:
	void print()
	{
		cout << "name: " << _name << endl;
		cout << "age: " << _age << endl;
	}
};

// struct 子类默认以 public 方式继承父类
struct Student : person
{
protected:
	int _stuid;
};

🌈 二、父类和子类对象赋值转换

  • 相近类型之间可以进行赋值类型转换,父子类对象也属于是相近类型,也可以进行赋值转换。
  • 子类对象可以赋值给父类的对象 / 父类的指针 / 父类的引用,这种做法被称之为切片,意思是将子类中属于父类的那部分切出来赋值过去。
  • 父类对象不能赋值给子类对象。
  • 父类的指针或者引用可以通过强制类型转换赋值给子类的指针或者引用,但是必须是父类的指针是指向子类对象时才是安全的。

举个栗子

  • 对于如下父类及其子类,父子类对象能够赋值和不能够赋值的情况如下:
// 父类
class Person
{
protected:
	string _name;	// 姓名
	string _sex;	// 性别
	int _age;		// 年龄
};

// 子类
class Student : public Person
{
public:
	int _stuid;		// 学号
};
  1. 子类对象可以切片赋值给父类的 对象 / 指针 / 引用。
Student sobj;
Person pobj = sobj;	// √ 子类对象赋值给父类对象
Person* pp = &sobj;	// √ 子类对象赋值给父类指针
Person& rp = sobj;	// √ 子类对象赋值给父类引用
  1. 父类对象不能赋值给子类对象。
Student sobj;
Person pobj;

sobj = pobj;		// × 父类对象不能赋值给子类对象
  1. 父类对象的指针可以通过强制类型转换赋值给子类的指针。
Student sobj;
Person pobj;

Person* pp = &sobj;
Student* ps1 = (Student*)pp; 	// 这种情况转换是可以的。
ps1->_stuid = 10;

pp = &pobj;
Student* ps2 = (Student*)pp; 	// 这种情况转换时虽然可以,但是会存在越界访问的问题
ps2->_stuid = 10;

⭐ 1. 子类对象赋值给父类的 对象 / 指针 / 引用

  • 子类对象可以通过切片将属于父类的那部分内容赋值给父类。
  1. 子类对象赋值给父类对象

image-20240908184319028

  1. 子类对象赋值给父类指针

image-20240908184408479

  1. 子类对象赋值给父类引用

image-20240908184510839

🌈 三、继承中的作用域

  1. 在继承体系中,父类子类都有自己独立的作用域
  2. 如果子类和父类中有同名成员,子类成员将屏蔽父类对同名成员的直接访问,这种情况被称之为隐藏,也叫做重定义
  3. 实际在继承体系中,最好不要定义同名的成员

举个栗子

  • 对于如下代码,访问父类的 _num 成员时会访问到子类的 _num 成员。
// 父类
class Person
{
protected:
	int _num = 111;
};

// 子类
class Student : public Person
{
public:
	void fun()
	{
		cout << _num << endl;
	}

protected:
    // 将继承过来的值为 111 的 _num 重定义成 999
	int _num = 999;	
};

int main()
{
	Student s;
	s.fun();	
	return 0;
}

image-20240908192003912

使用域作用限定符访问父类成员

  • 如果想要访问到父类的 _num 的内容,可以使用域作用限定符 :: 进行指定访问。
// 父类
class Person
{
protected:
	int _num = 111;
};

// 子类
class Student : public Person
{
public:
	void fun()
	{
        // 使用域作用限定符指定访问 Person 类的 _num 成员
		cout << Person::_num << endl;
	}

protected:
	int _num = 999;	
};

int main()
{
	Student s;
	s.fun();	
	return 0;
}

image-20240908192824778

如果是成员函数的隐藏,只需要函数名相同即可构成隐藏

// 父类
class Person
{
public:
	void fun(double x)
	{
		cout << "Person: " << x << endl;
	}
};

// 子类
class Student : public Person
{
public:
	void fun(int x)
	{
		cout << "Student: " << x << endl;
	}
};

int main()
{
	Student s;
	s.fun(2024);			// 会直接调用子类中的 fun 函数
	s.Person::fun(3.14);	// 指定调用父类当中的 fun 函数

	return 0;
}

image-20240908194841857

🌈 四、子类的默认成员函数

image-20240908200506115

⭐ 1. 子类中如何生成默认成员函数

  1. 子类的构造函数必须调用父类的构造函数初始化父类的那一部分成员
    • 如果父类没有默认的构造函数,则必须在子类构造函数的初始化列表中阶段显示调用。
  2. 子类的拷贝构造函数必须调用父类的拷贝构造完成父类的拷贝初始化
  3. 子类的赋值重载必须要调用父类的赋值重载完成对父类的复制
  4. 子类的析构函数会在被调用完后,自动调用父类的析构函数清理父类成员
    • 这样才能保证子类对象先清理子类成员,再清理父类成员的顺序。
  5. 子类对象在构造时,会先调用父类构造再调用子类构造
  6. 子类对象在析构时,会先调用子类析构再调用父类析构

举个栗子

  • 以 Person 类作为父类。
// 父类
class Person
{
private:
	string _name;

public:
	// 构造函数
	Person(const string& 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;
	}
};
  • 用 Student 类去继承 Person 类,子类 Student 中的默认成员函数如下:
// 子类
class Student : public Person
{
private:
	int _stuid; // 学号

public:
	//构造函数
	Student(const string& name, int stuid)
		: Person(name)	// 调用父类的构造函数初始化父类的那一部分成员
		, _stuid(stuid)	// 初始化子类的成员
	{
		cout << "Student()" << endl;
	}

	// 拷贝构造
	Student(const Student& s)
		: Person(s)			// 调用父类的拷贝构造函数完成对父类成员的拷贝构造
		, _stuid(s._stuid)	// 拷贝构造子类的成员
	{
		cout << "Student(const Student& s)" << endl;
	}

	// 赋值重载
	Student& operator=(const Student& s)
	{
		cout << "Student& operator=(const Student& s)" << endl;
		
		if (this != &s)
		{
			Person::operator=(s);	// 调用父类的赋值重载完成对父类成员的赋值
			_stuid = s._stuid;		// 完成子类成员的赋值
		}
		return *this;
	}

	// 析构函数
	~Student()
	{
		// 子类的析构函数会在被调用完成后再自动调用父类的析构函数
		cout << "~Student()" << endl;
	}
};

⭐ 2. 编写子类的默认成员函数时的注意事项

  1. 子类和父类的赋值重载函数会因为函数名相同而构成隐藏,因此在子类中调用父类的赋值重载时,需要使用域作用限定符指定调用父类的赋值重载函数
  2. 由于多态的原因,任何类的析构函数的函数名都会被统一处理为 destructor(),因此子类和父类也会因为函数名相同从而构成隐藏,也要使用域作用限定符指定调用父类的析构函数
  3. 在子类的拷贝构造和赋值重载中调用父类的拷贝构造和赋值重载的传参方式是一个切片行为,都是将子类对象直接赋值给父类的引用。

🌈 五、继承与友元

  • 友元关系不能继承,即父类的友元可以访问父类的私有和保护成员,但不能访问子类的私有和保护成员。

举个栗子

  • Display 函数是父类 Person 的友元函数,但不是子类 Student 的友元,即 Display 无法访问子类 Student 中的私有和保护成员。
class Student;

class Person
{
public:
	// 声明 Display 函数是父类 Person 的友元函数
	friend void Display(const Person& p, const Student& s);

protected:
	string _name;
};

class Student : public Person
{
protected:
	int _stuid;
};

void Display(const Person& p, const Student& s)
{
	cout << p._name << endl;	// 可以访问
	cout << s._stuid << endl;	// 无法访问
}

int main()
{
	Person p;
	Student s;

	Display(p, s);

	return 0;
}
  • 如果想让 Display 函数也能够访问子类 Student 中的私有和保护成员,必须让子类 Student 也将 Display 声明成友元函数。
class Student : public Person
{
public:
	// 声明 Display 函数是子类 Student 的友元函数
    friend void Display(const Person& p, const Student& s);

protected:
	int _stuid; 
};

🌈 六、继承与静态成员

  • 父类如果定义了一个 static 静态成员,则整个继承体系里就只能有一个该静态成员,无论派生出多少个子类,都只能有这一个 static 成员实例。

举个例子

  • 在父类 Person 中定义了静态成员变量 _count,虽然 Student 和 Graduate 都继承了 Person,但整个继承体系中只能有一个 _count 静态成员。
  • 如果在父类 Person 的构造和拷贝构造中让 _count 自增,就能通过 _count 来获已经实例化的 Person、Student 以及 Graduate 对象的总个数。
    • 由于子类在调用构造前会先调用父类的构造,因此只要知道调用了多少次 Person 的构造,即可知道这三个类的对象的总个数。
// 父类
class Person
{
public:
	Person()
	{
		_count++;
	}
	Person(const Person& p)
	{
		_count++;
	}

protected:
	string _name;			// 姓名

public:
	static int _count;		// 统计人的个数。
};

int Person::_count = 0;		// 静态成员变量必须在类外进行初始化

// 子类
class Student : public Person
{
protected:
	int _stuNum;			// 学号
};

// 子类
class Graduate : public Person
{
protected:
	string _seminarCourse;	// 研究科目
};

int main()
{
	Student s1;
	Student s2(s1);
	Student s3;
	Graduate s4;

	cout << Person::_count << endl;		// 4
	cout << Student::_count << endl;	// 4
	cout << Graduate::_count << endl;	// 4
	
	return 0;
}

image-20240909100745420

🌈 七、继承的方式

⭐ 1. 单继承

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

image-20240909101934946

⭐ 2. 多继承

  • 一个子类有两个或两个以上直接父类时,称这种继承关系为多继承。
    • 如:助教既可以是大学生的老师的同时也可以是博导的学生。

image-20240909102428269

  • 事物往往会具有多种特性,因此多继承本身不是什么大问题,但是由多继承延伸出来的菱形继承却会导致很多问题。

⭐ 3. 菱形继承

  • 菱形继承属于多继承的一种特殊情况,这种继承方式会出现数据冗余二义性的问题。

image-20240909102508124

1. 菱形继承会导致发生数据冗余和二义性问题

  • 对于上述菱形继承的模型,在实例化出 Assistant 对象后,会出现数据冗余问题,在访问成员时会出现二义性问题。
// 父类
class Person
{
public:
	string _name;			// 姓名
};

// 单继承自 Person 类的子类
class Student : public Person
{
protected:
	int _num;				// 学号
};

// 单继承自 Person 类的子类
class Teacher : public Person
{
protected:
	int _id;				// 职工编号
};

// 多继承自 Student 和 Teacher 类的子类
class Assistant : public Student, public Teacher
{
protected:
	string _major_course;	// 主修课程
};

int main()
{
	Assistant a;
	a._name = "peter";		// 二义性:无法明确知道要访问哪一个_name

	return 0;
}
  • 数据冗余问题:Student 和 Teacher 都继承自 Person 类,它们都拥有 Person 的成员,再让 Assistant 多继承自 Student 和 Teacher 会导致 Assistant 拥有两份 Person 类的成员。
  • 二义性问题:Assistant 对象多继承自 Student 和 Teacher 类,而 Student 和 Teacher 类都单继承自 Person 类,因此 Student 和 Teacher 类中都有含有 _name 成员,如果直接访问 Assistant 对象的 _name 成员,就不知道要访问的到底是 Student 还是 Teacher 的 _name 成员了。

image-20240909110159266

2. 解决二义性问题

  • 对于这种情况,可以使用域作用限定符让 Assistant 对象访问指定父类的 _name成员。
a.Student::_name = "张同学";
a.Teacher::_name = "张老师";
  • 这种方法虽然能够解决二义性,但由于 Assistant 对象中始终存在着两份 Person 类的成员,因此并不能解决数据冗余的问题,此时就需要用到菱形虚拟继承了。

🌈 八、菱形虚拟继承

  • 虚拟继承可以解决菱形继承的二义性和数据冗余的问题。

    • 如上面的继承关系,在 Student 和 Teacher 继承 Person 时使用虚拟继承,即可解决问题。
  • 虚拟继承只在菱形继承中使用,不要在其他地方使用。

⭐ 1. 虚拟继承格式

class 子类名 : virtual 继承方式 父类名
{
    // ......
};

⭐ 2. 虚拟继承样例

image-20240909111456461

// 父类
class Person
{
public:
	string _name;			// 姓名
};

// 虚拟继承自 Person 类的子类
class Student : virtual public Person
{
protected:
	int _num;				// 学号
};

// 虚拟继承自 Person 类的子类
class Teacher : virtual public Person
{
protected:
	int _id;				// 职工编号
};

// 多继承自 Student 和 Teacher 类的子类
class Assistant : public Student, public Teacher
{
protected:
	string _major_course;	// 主修课程
};

int main()
{
	Assistant a;
	a._name = "peter";		// 无二义性

	return 0;
}
  • 解决了二义性的问题:此时可以直接访问 Assistant 对象的 _name 成员,之后就算指定访问 Assistant 的 Student 父类和 Teacher 父类的 _name 成员,访问到的都是同一个结果。

image-20240909112423983

  • 解决了数据冗余的问题:打印 Assistant 的 Student 父类和 Teacher 父类的 _name 成员的地址时,显示的也是同一个地址。

image-20240909112623464

⭐ 3. 虚拟继承位置

  • 很多时候菱形继承并不一定就是一个标准的菱形,虚拟继承要放置在直接继承自会出现数据冗余部分的类上。
    • 如:上述代码中,Person 类中的成员会出现数据冗余,virtual 就要加在直接继承 Person 类的子类当中。

image-20240909113735549

⭐ 4. 虚拟继承原理

  • 为了研究虚拟继承原理,现在实现一个简单的菱形继承继承体系,再借助内存窗口观察对象成员的模型

1. 未使用虚拟继承时的内存分布情况

image-20240909160942324

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;
}
  • D 类对象包含 2 份 A 类的成员,出现了数据冗余和二义性问题。

image-20240909162716468

2. 使用了虚拟继承时的内存分布情况

image-20240909163159717

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;

	return 0;
}
  • D 类对象的各个成员在内存中的分布情况如下:

image-20240909171456525

  • D 类对象中属于 A 类的 _a 成员被放在了最后,而在原来存放属于 B 和 C 类的两个 _a 成员的位置变成了指针。
  • B 和 C 的这两个指针被称作虚基表指针,它们分别指向一张虚基表,此时就是通过 B 和 C 的这两个指针找到各自对应的虚基表。
  • 虚基表中存储的是所有从父类继承过来的成员的偏移量,通过起始地址 + 指定的 _a 成员的偏移量能够找到最下面的 A 类的 _a。
    • 如:B 的虚基表指针指向的虚基表中存储的 _a 偏移量是 14 (16进制),让 B 的起始地址 5C + 14 就能找到位于 70 处的 _a 的地址。
  • 即 B 和 C 通过自身的起始地址 + 指定成员 _a 的偏移量,最终都能够找到 A 类的 _a 成员。

🌈 九、继承笔试面试题

1. 什么是菱形继承?菱形继承的问题是什么?

  • 菱形继承是多继承的一种特殊情况,多个个子类继承同一个父类,而又有子类同时继承这多个个子类,我们称这种继承为菱形继承。
  • 菱形继承因为子类对象当中会有多份父类的成员,因此会导致数据冗余和二义性的问题。

2. 什么是菱形虚拟继承?如何解决数据冗余和二义性的问题?

  • 菱形虚拟继承是指在会发生数据冗余的类的直接子类使用虚拟继承 virtual 的继承方式,菱形虚拟继承对于 D 类对象当中重复的 A 类成员只存储一份,然后采用虚基表指针和虚基表使得 D 类对象当中继承的 B 类和 C 类可以找到自己继承的A类成员,从而解决了数据冗余和二义性的问题。

3. 继承和组合的区别?什么时候用继承?什么时候用组合?

  • 继承是一种 is-a 的关系,而组合是一种 has-a 的关系。
  • 如果两个类之间是 is-a 的关系,使用继承;如果两个类之间是 has-a 的关系,则使用组合。
  • 如果两个类之间的关系既可以看作 is-a 的关系,又可以看作 has-a 的关系,则优先使用组合。

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

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

相关文章

分布式通信:多计算平台的任务分配

目录 1. 分布式通信 1.1 树莓派配置流程​编辑 1.2 树莓派和laptop处于同一网络​编辑 1.3 laptop配置 1.4 通信测试 1.5 分组通信 ​编辑 1.6 分布式通信测试 ​编辑参考资料 1. 分布式通信 机器人体积较小&#xff0c;采用树莓派作为控制器&#xff0c;实现传感器处…

仿某皮影狸app官网源码 不错的APP下载官网单页源码 HTML源码

分享一款不错的APP下载官网单页源码&#xff0c;直接修改index.html即可 源码下载&#xff1a;https://download.csdn.net/download/m0_66047725/89731228 更多资源下载&#xff1a;关注我。

OFDM系统PAPR算法的MATLAB仿真,对比SLM,PTS以及CAF,对比不同傅里叶变换长度

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1、选择映射&#xff08;SLM&#xff09; 4.2 相位截断星座图&#xff08;PTS&#xff09; 5.算法完整程序工程 1.算法运行效果图预览 (完整程序运行后无水印) 2.算法运行软件版本 mat…

极狐GitLab 新一代容器镜像仓库正式上线啦!

从极狐GitLab 17.3 开始&#xff0c;私有化部署实例也可以使用新一代容器镜像仓库啦&#xff01;新一代容器镜像仓库具有更高效的零宕机垃圾收集功能和其他优势。 从去年开始&#xff0c;极狐GitLab 就启动了重构容器镜像仓库的计划&#xff0c;用以构建具有更强功能的镜像仓库…

就服务器而言,ARM架构与X86架构有什么区别?各自的优势在哪里?

一、服务器架构概述 在数字化时代&#xff0c;服务器架构至关重要。服务器是网络核心节点&#xff0c;存储、处理和提供数据与服务&#xff0c;是企业和组织信息化、数字化的关键基础设施。ARM 和 x86 架构为服务器领域两大主要架构&#xff0c;x86 架构服务器在市场占主导&…

弹框调取阿里云播放器一直报错 TypeError: 没有为播放器指定容器

弹框调取阿里云播放器一直报错 TypeError: 没有为播放器指定容器 <template><el-dialogv-model"dialogpeopleVisible":before-close"handleClose"class"aliyunplayDialog"><!-- :show-close "false" --><div&g…

2024年企业级电脑监控软件推荐,精选的电脑监控软件

随着企业信息化程度的不断提高&#xff0c;如何有效监控和管理企业电脑成为许多企业主和IT管理员的重要任务。企业级电脑监控软件不仅可以帮助企业提高工作效率&#xff0c;保障数据安全&#xff0c;还能够防止内部数据泄露和违规操作。在2024年&#xff0c;有多款优秀的电脑监…

一帧图像绘制过程(详解)

一帧图像的起始 手机流畅使用会带来良好的用户体验&#xff0c;而流畅的手机画面是通过屏幕刷新频率和稳定的帧率相配合实现。过高或过低的帧率会造成资源的浪费&#xff0c;不稳定的帧率造成卡顿等现象&#xff0c;影响用户体验。那么稳定的帧率如何实现&#xff1f;或者说一帧…

【C++第十四课-map和set】set的用法、multiset、map的用法、multimap

目录 setset的用法set功能&#xff1a;排序去重反向迭代器finderasecountlower_bound、upper_bound multiseterasecountfind mapmap的构造findmultimap计算出现的次数[ ]insert 题目 之前学的都只是存储数据 在初阶阶段&#xff0c;我们已经接触过STL中的部分容器&#xff0c;比…

Python机器学习——利用Keras和基础神经网络进行手写数字识别(MNIST数据集)

Python机器学习——利用Keras和基础神经网络进行手写数字识别&#xff08;MNIST数据集&#xff09; 配置环境创建虚拟环境安装功能包并进环境 编程1. 导入功能包2. 加载数据集3. 数据预处理4. 构建神经网络5. 神经网络训练6. 测试模型训练效果 配置环境 首先安装Anaconda&…

vue3_对接腾讯_实时音视频

项目需要对接腾讯的实时音视频产品&#xff0c;我这里选择的是多人会议&#xff0c;选择其他实时音视频产品对接流程也一样&#xff0c;如何对接腾讯实时音视频的多人会议产品&#xff0c;从开通服务到对接完成&#xff0c;一 一讲解。 一、开通腾讯实时音视频 1.腾讯实时音视…

适用于计算机视觉的机器学习

使用筛选器将效果应用于图像的功能在图像处理任务中非常有用&#xff0c;例如可能使用图像编辑软件执行的任务。 但是&#xff0c;计算机视觉的目标通常是从图像中提取含义或至少是可操作的见解&#xff0c;这需要创建经过训练以基于大量现有图像识别特征的机器学习模型。 卷积…

Unet改进30:添加CAA(2024最新改进方法)|上下文锚定注意模块来捕获远程上下文信息。

本文内容:在不同位置添加CAA注意力机制 目录 论文简介 1.步骤一 2.步骤二 3.步骤三 4.步骤四 论文简介 遥感图像中的目标检测经常面临一些日益严峻的挑战,包括目标尺度的巨大变化和不同的测距环境。先前的方法试图通过大核卷积或扩展卷积来扩展主干的空间感受野来解决这…

cfs三层靶机——内网渗透

目录 1、环境地址 2、安装教程 3、配置虚拟机网卡 4、网络拓扑 5、安装宝塔 6、渗透测试 7、CentOS7 8、ubuntu 1、生成木马并上传 2、在kali上开启监听 3、回到蚁剑&#xff0c;运行木马 4、制作跳板 1、添加路由 2、查看路由 3、配置代理 4、配置kali的代理&…

第九届“创客中国”生成式人工智能(AIGC)中小企业创新创业大赛圆满落幕

9月5日,第九届“创客中国”生成式人工智能(AIGC)中小企业创新创业大赛在南昌降下了帷幕。工业和信息化部网络安全产业发展中心(工业和信息化部信息中心)主任付京波;江西省工业和信息化厅党组成员、副厅长郭启东;南昌市委常委、市委秘书长、办公室主任赵捷;市中小企业局党组书记…

MFC工控项目实例之十二板卡测试信号输出界面

承接专栏《MFC工控项目实例之十一板卡测试信号输入界面》 1、在BoardTest.h文件中添加代码 CButtonST m_btnStart[16],m_btnStart_O[16];2、在BoardTest.cpp文件中添加代码 UINT No_IDC_CHECK_O[16] {IDC_CHECK16,IDC_CHECK17,IDC_CHECK18,IDC_CHECK19,IDC_CHECK20,IDC_CH…

Idea 创建 Maven项目的时候卡死

文章目录 一、Archetype 和 Catalog1.1 Archetype&#xff08;原型&#xff09;1.2 Catalog&#xff08;目录&#xff09; 二、可能遇到的问题2.1 问题描述2.2 原因分析2.3 解决方案 参考资料 一、Archetype 和 Catalog 1.1 Archetype&#xff08;原型&#xff09; Archetype…

vue3+ant design vue实现文件上传(阿里云oss)~

1、效果图 2、自定义上传 <a-upload v-model:file-list"fileList" name"导入员工" action"" :customRequest"upDown" :beforeUpload"beforeUpload" :onChange"handleChange" remove"removeFile" ac…

【自然语言处理】实验一:基于NLP工具的中文分词

目录 前言 1. 导入jieba分词器 2. 用精确模式进行中文分词 3. 用全模式进行中文分词 4. 用搜索引擎进行中文分词 5. 利用 lcut返回结果列表(list) 总结 &#x1f308;嗨&#xff01;我是Filotimo__&#x1f308;。很高兴与大家相识&#xff0c;希望我的博客能对你有所帮助。 &a…

Typora调整图片大小的两种方式:zoom或width/height

目录 01 zoom方式02 width/height方式2.1 width方式 2.2 height方式 01 zoom方式 语法: <img src"your-image-url" style"zoom:your-zoom-integer"/> 示例&#xff1a;将图片(./image/market.jpg)调整为原图减少50%大小的命令为&#xff1a; …