【032】C++高级开发之继承机制详解(最全讲解)

news2024/11/15 5:48:29

C++的继承机制详解

  • 引言
  • 一、继承和派生
    • 1.1、继承的概念和意义
    • 1.2、派生类的定义
  • 二、继承中的构造和析构
    • 2.1、子类的构造和析构顺序
    • 2.2、子类调用成员对象、父类的有参构造
  • 三、子类和父类的同名处理
    • 3.1、子类和父类同名成员数据
    • 3.2、子类和父类同名成员函数
    • 3.3、子类重定义父类的同名函数
  • 四、子类不能继承父类的哪些成员?
  • 五、多继承
    • 5.1、多继承的概念
    • 5.2、多继承中的同名成员处理
  • 六、菱形继承
  • 七、虚继承
    • 7.1、虚继承的方式
    • 7.2、通过VS查看虚继承的实现原理
  • 总结

引言


💡 作者简介:专注于C/C++高性能程序设计和开发,理论与代码实践结合,让世界没有难学的技术。包括C/C++、Linux、MySQL、Redis、TCP/IP、协程、网络编程等。
👉
🎖️ CSDN实力新星,社区专家博主
👉
🔔 专栏介绍:从零到c++精通的学习之路。内容包括C++基础编程、中级编程、高级编程;掌握各个知识点。
👉
🔔 专栏地址:C++从零开始到精通
👉
🔔 博客主页:https://blog.csdn.net/Long_xu


🔔 上一篇:【031】C++类和对象之运算符重载详解和代码实践(最全讲解)

一、继承和派生

1.1、继承的概念和意义

C++继承是一种面向对象编程的重要特性,它允许程序员创建一个新类(称为派生类或子类),该类可以从另一个现有类(称为基类或父类)继承属性和行为。这意味着派生类会自动拥有基类中的所有成员变量和成员函数,并且可以在此基础上进行修改、扩展和优化。
在这里插入图片描述

C++最重要的特征是代码重用,通过继承机制可以利用已有的数据类型来重新定义新的数据类型,新的类不仅有旧类的成员,还拥有新定义的成员。
一个B类继承于A类,或者说从类A派生类B;这样一来,类A成为了基类(父类),类B称为派生类(子类)。派生类中的成员包含两部分:一部分是从基类中继承过来的,一部分是自己增加的成员。从基类继承过来的表现其共性,而新增的成员体现其个性。
在这里插入图片描述

继承的主要作用是提高代码的复用性和可维护性,提高开发效率。通过将公共部分放在基类中定义,不同的派生类只需要添加其特定功能即可,避免了代码冗余,并且使得修改更加容易。另外,继承还支持多态性,即同一个方法名可以在不同的子类中具有不同的实现,这大大增强了程序灵活性和可扩展性。

1.2、派生类的定义

语法:

class 父类{
};

class 子类:继承方式 父类{
// 新增子类数据
};

继承方式有:

  • private
  • protected
  • public(推荐)

在这里插入图片描述
所有父类的私有数据在子类中不可访问,公共继承保持不必,保护继承变保护,私有继承变私有。

示例:

#include <iostream>
using namespace std;

class A{
private:
	int a;
protected:
	int b;
public:
	int c;
};

class B:public A{
public:
	void func(void)
	{
		//cout<<a<<endl; // error,不可访问
		cout<<b<<c<<endl;
	}
};

int main()
{
	B ob;
	//cout<<ob.b<<endl;// error,不可访问
	cout<<ob.c<<endl;// OK
	return 0;
}

二、继承中的构造和析构

2.1、子类的构造和析构顺序

C++子类的构造和析构顺序如下:

  1. 当创建子类对象时,首先会调用父类的默认构造函数来初始化父类部分。

  2. 然后调用子类的构造函数来初始化子类部分。在子类构造函数中可以通过初始化列表调用父类的有参构造函数或者其他构造函数。

  3. 如果子类没有定义自己的析构函数,则会使用默认的析构函数。当销毁一个子类对象时,首先会调用子类的析构函数,然后再调用父类的析构函数。

  4. 如果子类定义了自己的析构函数,则需要在其中显式地调用父类的析构函数以确保正确释放资源。

在这里插入图片描述

示例:

#include <iostream>
using namespace std;

class Base {
public:
	Base()
	{
		cout << "Base构造函数" << endl;

	}
	~Base()
	{
		cout << "Base析构函数" << endl;
	}
};

class Other {
public:
	Other()
	{
		cout << "Other构造函数" << endl;

	}
	~Other()
	{
		cout << "Other析构函数" << endl;
	}
};

class Son:public Base {
private:
	Other ot;
public:
	Son()
	{
		cout << "Son构造函数" << endl;

	}
	~Son()
	{
		cout << "Son析构函数" << endl;
	}
};

int main()
{
	Son ob;

	return 0;
}

输出:

Base构造函数
Other构造函数
Son构造函数
Son析构函数
Other析构函数
Base析构函数

2.2、子类调用成员对象、父类的有参构造

子类实例化对象时会自动调用成员对象、父类的默认构造函数。
子类实例化对象时必须使用初始化列表调用 成员对象、父类的有参构造。
初始化列表时:父类写类名称,成员对象用对象名。

示例:

#include <iostream>
using namespace std;

class Base {
public:
	int a;
public:
	Base()
	{
		cout << "Base构造函数" << endl;

	}
	Base(int a)
	{
		cout << "Base有参构造函数" << endl;
		this->a = a;

	}
	~Base()
	{
		cout << "Base析构函数" << endl;
	}
};

class Other {
public:
	int b;
public:
	Other()
	{
		cout << "Other构造函数" << endl;

	}
	Other(int b)
	{
		cout << "Other有参构造函数" << endl;
		this->b = b;

	}
	~Other()
	{
		cout << "Other析构函数" << endl;
	}
};

class Son:public Base {
private:
	Other ot;
public:
	int c;
public:
	Son()
	{
		cout << "Son构造函数" << endl;

	}
	Son(int a, int b, int c) :Base(a), ot(b)
	{
		cout << "Son有参构造函数" << endl;
		this->c = c;
	}
	~Son()
	{
		cout << "Son析构函数" << endl;
	}
};

int main()
{
	Son ob(100,200,300);

	return 0;
}

输出:

Base有参构造函数
Other有参构造函数
Son有参构造函数
Son析构函数
Other析构函数
Base析构函数

三、子类和父类的同名处理

同名成员 最简单 最安全的处理方式:加作用域。主要是加父类的作用域,如果是访问子类的成员不需要加作用域即可默认访问子类的成员,所以要访问父类的成员最好加上父类的作用域。

3.1、子类和父类同名成员数据

子类默认优先访问子类的同名成员。必须加父类作用域访问父类的同名成员。

示例:

#include <iostream>
using namespace std;

class Base {
public:
	int a;
public:
	Base()
	{
		cout << "Base构造函数" << endl;

	}
	Base(int a)
	{
		cout << "Base有参构造函数" << endl;
		this->a = a;

	}
	~Base()
	{
		cout << "Base析构函数" << endl;
	}
};

class Son:public Base {
public:
	int a;
public:
	Son()
	{
		cout << "Son构造函数" << endl;

	}
	Son(int a, int b) :Base(a)
	{
		cout << "Son有参构造函数" << endl;
		this->a = b;
	}
	~Son()
	{
		cout << "Son析构函数" << endl;
	}
};

int main()
{
	Son ob(100,200);
	// 子类默认优先访问子类的同名成员
	cout << ob.a << endl;// 输出200
	
	// 必须添加父类作用域访问父类的同名成员
	cout << ob.Base::a << endl;// 输出100

	return 0;
}

输出:

Base有参构造函数
Son有参构造函数
200
100
Son析构函数
Base析构函数

3.2、子类和父类同名成员函数

与子类和父类同名成员数据类似。

示例:

#include <iostream>
using namespace std;

class Base {
public:
	int a;
public:
	Base()
	{
		cout << "Base构造函数" << endl;

	}
	Base(int a)
	{
		cout << "Base有参构造函数" << endl;
		this->a = a;

	}
	void func()
	{
		cout << "Base无参 func 函数" << endl;
	}
	~Base()
	{
		cout << "Base析构函数" << endl;
	}
};

class Son:public Base {
public:
	int a;
public:
	Son()
	{
		cout << "Son构造函数" << endl;

	}

	Son(int a, int b) :Base(a)
	{
		cout << "Son有参构造函数" << endl;
		this->a = b;
	}
	void func()
	{
		cout << "Son无参 func 函数" << endl;
	}

	~Son()
	{
		cout << "Son析构函数" << endl;
	}
};

int main()
{
	Son ob(100,200);
	// 子类默认优先访问子类的同名成员
	cout << "----------------------------" << endl;
	ob.func();
	// 必须添加父类作用域访问父类的同名成员
	ob.Base::func();
	cout << "----------------------------" << endl;

	return 0;
}

输出:

Base有参构造函数
Son有参构造函数
----------------------------
Son无参 func 函数
Base无参 func 函数
----------------------------
Son析构函数
Base析构函数

3.3、子类重定义父类的同名函数

重载:无继承,同一作用域,参数的个数不同、顺序不同、类型不同都可以重载。
重定义:有继承,子类重定义父类的同名函数(参数可以不同,非虚函数),子类一旦重定义了父类的同名函数(不管参数是否一致),子类都将屏蔽父类所有的同名函数。重定义是继承之间的一个重载,子类重载父类的同名函数。

示例:

#include <iostream>
using namespace std;

class Base {
public:
	void func()
	{
		cout << "Base无参 func 函数" << endl;
	}
	void func(int a)
	{
		cout << "Base 一个参数 func 函数" << endl;
	}
	void func(int a,int b)
	{
		cout << "Base 两个参数 func 函数" << endl;
	}
};


class Son:public Base {

public:
	void func(const char *str)
	{
		cout << "Son char*参数的 func 函数" << endl;
		cout << str << endl;
	}
};

int main()
{
	Son ob;
	cout << "----------------------------" << endl;
	ob.func("hello,world");
	// ob.func();			// 屏蔽了,不识别父类的func
	// ob.func(100);		// 屏蔽了,不识别父类的func
	// ob.func(100,200);	// 屏蔽了,不识别父类的func
	cout << "----------------------------" << endl;

	// 需要加父类的作用域才能识别屏蔽的函数
	ob.Base::func();
	ob.Base::func(100);	
	ob.Base::func(100,200);

	return 0;
}

输出:

----------------------------
Son char*参数的 func 函数
hello,world
----------------------------
Base无参 func 函数
Base 一个参数 func 函数
Base 两个参数 func 函数

四、子类不能继承父类的哪些成员?

不是所有的函数都能自动从基类继承到派生类。不能继承的成员:

  • 构造函数。
  • 析构函数。
  • operator=。

构造函数和析构函数用来处理对象的创建和析构操作,构造和析构函数只知道对它们的特定层次的对象做什么,不能被继承,必须为每个特定的派生类分别创建。

另外,operator也不能被继承,因为它完成类似构造函数行为。尽管我们知道如何由=右边对象初始化-左边对象的所有成员,但这不意味着对派生类依旧有效。

在继承中,如果没有创建这些函数,编译器自动生成它们。

五、多继承

5.1、多继承的概念

C++的多继承是指一个类可以从多个基类中继承数据和函数成员。这种机制允许程序员将不同的功能集成到一个类中,以便更好地组织代码和实现复杂的功能。

多继承是非常受争议的,从多个类继承可能导致函数、变量等同名造成较多的歧义。

在C++中,多继承的语法形式如下:

class Derived : access-specifier Base1, access-specifier Base2, ..., access-specifier BaseN {
    //...
};

其中Derived是派生类,Base1、Base2、…、BaseN都是基类,access-specifier表示派生类对基类的访问权限(public、protected或private)。

示例:

#include <iostream>
using namespace std;

class Base1{
public:
	int a;
public:
	void func()
	{
		cout<<"Base1 func"<<endl;
	}
};

class Base2{
public:
	int b;
public:
	void func2()
	{
		cout<<"Base2 func"<<endl;
	}
};

class Son:public Base1,public Base2{
public:
	int c;
};

int main()
{
	Son obj;
	cout<<obj.a<<obj.b<<obj.c<<endl;// OK
	return 0;
}

5.2、多继承中的同名成员处理

在多继承中,如果不同的基类拥有相同名称的成员函数或数据成员,则需要通过作用域限定符明确调用所需的成员。例如:

class A {
public:
    void func() { cout << "A::func" << endl; }
};

class B {
public:
    void func() { cout << "B::func" << endl; }
};

class C : public A, public B {
public:
    void test() {
        A::func(); // 明确调用A中的func
        B::func(); // 明确调用B中的func
    }
};

此外,在多继承中也存在菱形继承问题,即当一个派生类同时从两个不同的基类继承某个共同父类时,会出现重复定义和二义性等问题。为了解决这个问题,C++提供了虚拟继承(virtual inheritance)的机制。

六、菱形继承

有公共祖先的继承,称为菱形继承。最底层的子类数据会包含多份(公共祖先的数据)。
菱形继承是指一个派生类同时继承两个基类,而这两个基类又间接或直接继承同一个虚基类的情况。
在这里插入图片描述示例:

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;
};

在上述代码中,A 是虚基类,B 和 C 都从 A 继承。D 类通过多重继承同时从 B 和 C 继承,并且由于 B 和 C 都从 A 虚拟继承,因此 D 只会得到一个 A 的实例。

菱形继承带来的问题主要是二义性和空间浪费。例如,在上述代码中如果有以下函数:

void func(D* d) {
    d->a = 1; // 哪个 a?
}

这里就不知道应该访问哪个 a 变量了。这时候可以通过指定作用域来访问,例如:

void func(D* d) {
    d->B::a = 100;
    d->C::a = 200;
}

为了避免这些问题,在使用多重继承时需要特别小心并且合理设计程序结构。

七、虚继承

针对菱形继承,能不能只要公共祖先的一份数据呢?可以通过虚继承解决菱形继承中多份公共祖先数据的问题。

7.1、虚继承的方式

虚继承是 C++ 中用于解决多重继承中出现的菱形继承问题的一种技术。在虚继承中,派生类通过 virtual 关键字指定从基类进行继承,这样就可以保证只有一个实例存在。

例如:

#include <iostream>
using namespace std;

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 obj;
	cout<<obj.a<<endl;// 可以访问
	return 0;
}

在上述代码中,B 和 C 都通过虚拟继承方式从 A 继承,这样 D 类只会得到一个 A 的实例,从而避免了菱形继承所带来的二义性和空间浪费问题。

在使用虚继承时需要特别小心并且合理设计程序结构。由于虚继承需要额外的时间和空间开销,因此应该遵循“最小依赖原则”,即尽可能减少对基类的依赖关系,并且将共同部分抽象成接口或抽象基类。

7.2、通过VS查看虚继承的实现原理

首先建立一个项目,输入如下代码:

#include <iostream>
using namespace std;

class MyA {
public:
	int a;
};

class MyB : virtual public MyA {
public:
	int b;
};

class MyC : virtual public MyA {
public:
	int c;
};

class MyD : public MyB, public MyC {
public:
	int d;
};
int main()
{
	MyD obj;
	obj.a = 100;
	cout << obj.a << endl;// 可以访问
	return 0;
}

(1)打开命令行开发者模式。
在这里插入图片描述
(2)找到类所在源文件的路径(右击项目解决方案)。
在这里插入图片描述

(3)命令行切到源文件目录。
在这里插入图片描述

(4)在命令行中导出类的布局。
格式:

cl /d1 reportSingleClassLayout<自己的类名称> 源文件名

例如:

cl /d1 reportSingleClassLayoutMyD main.cpp

(5)各个类的布局情况。

MyA的布局:

main.cpp

class MyA       size(4):
        +---
 0      | a
        +---
Microsoft (R) Incremental Linker Version 14.16.27045.0
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:main.exe
main.obj

MyB的布局:

class MyB       size(12):
        +---
 0      | {vbptr}
 4      | b
        +---
        +--- (virtual base MyA)
 8      | a
        +---

MyB::$vbtable@:
 0      | 0
 1      | 8 (MyBd(MyB+0)MyA)
vbi:       class  offset o.vbptr  o.vbte fVtorDisp
             MyA       8       0       4 0
Microsoft (R) Incremental Linker Version 14.16.27045.0
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:main.exe
main.obj

MyC的布局:

class MyC       size(12):
        +---
 0      | {vbptr}
 4      | c
        +---
        +--- (virtual base MyA)
 8      | a
        +---

MyC::$vbtable@:
 0      | 0
 1      | 8 (MyCd(MyC+0)MyA)
vbi:       class  offset o.vbptr  o.vbte fVtorDisp
             MyA       8       0       4 0
Microsoft (R) Incremental Linker Version 14.16.27045.0
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:main.exe
main.obj

MyD的布局:

main.cpp

class MyD       size(24):
        +---
 0      | +--- (base class MyB)
 0      | | {vbptr}
 4      | | b
        | +---
 8      | +--- (base class MyC)
 8      | | {vbptr}
12      | | c
        | +---
16      | d
        +---
        +--- (virtual base MyA)
20      | a
        +---

MyD::$vbtable@MyB@:
 0      | 0
 1      | 20 (MyDd(MyB+0)MyA)

MyD::$vbtable@MyC@:
 0      | 0
 1      | 12 (MyDd(MyC+0)MyA)
vbi:       class  offset o.vbptr  o.vbte fVtorDisp
             MyA      20       0       4 0
Microsoft (R) Incremental Linker Version 14.16.27045.0
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:main.exe
main.obj

可以看出,虚继承会在子类中产生虚基类指针(vbptr)指向虚基类表(vbtable),虚基类表记录的是通过该指针访问公共祖先的数据的偏移量。

注意:
虚继承只能解决具备公共祖先的多继承带来的二义性问题,不能解决没有公共祖先的多继承。在工程开发中真正意义上的多继承几乎不被使用,因为多继承带来的代码复杂性远大于其带来的便利性;多继承对代码维护上的影响是灾难性的,在设计方法上任何多继承都可以被单继承替代。

总结

C++继承机制是面向对象编程的核心概念之一,它通过子类继承父类的属性和方法实现代码复用和扩展。以下是C++继承机制的总结:

(1) 继承类型。C++中有3种继承类型:公有继承、私有继承和保护继承。

  • 公有继承(public inheritance):子类可以访问父类的公有成员和保护成员,但不能访问父类的私有成员。
  • 私有继承(private inheritance):子类可以访问父类的公有成员、保护成员和私有成员,但在外部不能通过子类对象访问这些成员。
  • 保护继承(protected inheritance):子类可以访问父类的公有成员和保护成员,但不能访问父类的私有成员,在外部也不能通过子类对象访问这些成员。

(2) 构造函数和析构函数。子类对象创建时会先调用父类的构造函数,再调用自己的构造函数;而销毁时则相反,先调用自己的析构函数,再调用父类的析构函数。同时需要注意虚析构函数和多重继承时可能会出现死循环等问题。

(3) 虚函数。虚函数是用于多态的重要机制,子类可以通过覆盖(override)父类的虚函数实现自己的行为。当调用一个指向父类对象的指针或引用时,如果该对象被子类继承并重写了虚函数,则会调用子类中的对应函数。

(4)虚继承。当存在多个继承路径时,可能会导致同一个父类在内存中有多个拷贝,造成浪费和不一致。此时可以使用虚继承(virtual inheritance),让所有从同一基类派生出来的子类共享该基类,在内存中只保留一个拷贝。

(5)多重继承。C++允许同时从多个父类继承属性和方法,称为多重继承。但需要注意解决命名冲突、二义性和虚表等问题。

在这里插入图片描述

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

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

相关文章

2.5C++多重继承

C 多重继承概述 C中的多重继承是指一个派生类可以从多个基类中继承属性和方法。 多重继承的作用是让 C 中的类更灵活地组合&#xff0c;以及实现代码的高复用。 多重继承的语法如下&#xff1a; access_specifier可以是public、protected或private&#xff0c;用来指定继承…

python学习——文本数据处理

目录 1 计算长度 len2 大小写 lower、upper、title、capitalize、swapcase3 字符检索 get、slice4 元素提取 findall、extract5 索引操作 find、index6 字符类型判断,结果一定是True或False7 字符判断 contains、startswith、endswith8 替换 replace9 字符的分割 split、partit…

鸿蒙HarmonyOS开发环境初识及搭建

一 鸿蒙简介 HarmonyOS是一款面向万物互联时代的、全新的分布式操作系统。在传统的单设备系统能力基础上&#xff0c;HarmonyOS提出了基于同一套系统能力、适配多种终端形态的分布式理念&#xff0c;能够支持手机、平板、智能穿戴、智慧屏、车机等多种终端设备&#xff0c;提供…

A Sequence-to-Set Network for Nested Named Entity Recognition

原文链接&#xff1a; https://www.ijcai.org/proceedings/2021/0542.pdf IJCAI 2021 介绍 问题 将嵌套NER视为span分类任务存在两个缺陷&#xff0c;不仅搜索空间大还缺少了实体之间的交互。 IDEA 因此作者提出了sequence-to-set的模型&#xff0c;不再提前给定span&#x…

【数据分享】全国县市2000-2021年农业、工业数据(免费获取)

《中国县域统计年鉴》是一部全面反映我国县域社会经济发展状况的资料性年鉴&#xff0c;收录了上一年度全国2000多个县域单位的基本情况、综合经济、农业、工业、教育、卫生、社会保障等方面的资料。 之前基于《中国县域统计年鉴》我们分享了2000至2021年的综合经济数据&#…

详解eslint在vue中如何使用

ESLint在vue中的使用 阅读目录 .editorconfig文件&#xff08;主要用于配置IDE&#xff09;.eslintignore文件&#xff08;放置需要ESLint忽略的文件&#xff0c;只对.js文件有效&#xff09;.eslintrc.js 文件(用来配置ESLint的检查规则) ESLint的用途 1.审查代码是否符合编…

SwinTransformer与Vit细节总结

建议通过标题来快速跳转 Vit (Vision Transformer) Vit把图片打成了patch&#xff0c;然后过标准的TransformerEncoder&#xff0c;最后用CLS token来做分类 Vit的位置编码 作者在文中试了几种方式&#xff0c;发现这几种在分类上效果差不多 1-dimensional positional emb…

EMQ 明道云:零代码高效构建工业物联网设备管理平台

背景 智能物联网设备在 IIoT 场景中有着广泛的应用&#xff0c;但如何管理和监控这些设备是一个挑战。 明道云是一家专业的 hpaPaaS 平台服务商&#xff0c;其所开发的明道云平台&#xff08;Mingdao Cloud&#xff09;是一个企业软件设计和开发工具&#xff0c;让企业可以低…

[230608] 阅读TPO58汇总|7:30-9:00+17:05

目录 ​​​​​​​ TPO58 1 The Development of Instrumental Music [3]修辞目的题 举例说明的作用 [9]句子插入题 [10]小结题 2 Pinyon Pines and Pinyon Jays [4]否定事实信息题 [5]修辞目的题 段落在全篇的作用 [10]小结题 3 The Rise of Classic Maya Civi…

SecCertificate 解析

一、SecCertificate A digital certificate is a collection of data used to securely distribute the public half of a public/private key pair. 数字证书 1. 结构 2. 读取和存储 2.1 Identity var certificate: SecCertificate? let status SecIdentityCopyCertific…

12.分布式事务流程与事务消息源码分析

highlight: arduino-light Rocket事务流程&源码分析 Rocket解决分布式事务流程 事务消息分 2 个阶段&#xff1a; ① 正常事务消息的发送与提交&#xff1a; a.发送消息(half 消息) b.服务响应消息写入结果 c.根据发送结果执行本地事务(如果写入失败&#xff0c;此时half消…

Midjourney使用教程:三 图片风格提示

这里我根据现在的官方文档来继续我们的Midjourney的教程&#xff0c;看到这里如果你去实践的话&#xff0c;估计你已经有了好多张属于自己的图片。 这时候你不在满足简单的提示生成的Midjourney的默认风格图片&#xff0c;实际上你可以通过一些关键词做提示&#xff0c;来改变…

初始网络原理

目录 网络发展史 独立模式 网络互连 局域网LAN 广域网WAN 网络通信基础 IP地址 端口号 认识协议 五元组 协议分层 OSI七层模型 TCP/IP五层&#xff08;或四层&#xff09; 网络设备所在分层 封装和分用 网络发展史 独立模式 独立模式&#xff1a;计算机之间相互…

第八十三天学习记录:计算机硬件技术基础:汇编语言程序设计

一、汇编语言指令 汇编语言的语句是在指令系统的基础上形成的&#xff0c;按其作用与编译情况分为两大类&#xff1a;指令性语句&#xff08;符号指令&#xff09;和指示性语句&#xff08;伪指令&#xff09;。 指令性语句是可执行语句&#xff0c;与机器指令相对应&#xff…

USB转换方案介绍

随着科技的不断发展&#xff0c;我们的生活中出现了越来越多的电子设备。然而&#xff0c;这些设备通常具有不同的连接端口和协议&#xff0c;这可能会使它们之间的连接变得困难。这时候&#xff0c;使用USB转换就成为了一种非常方便和实用的解决方法。 无论是在家庭、办公室还…

自动化测试——处理场景自动化测试场景详细,跟着上高速

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、定位一组对象 …

城市消防应急通信三级作战网构建

项目背景 随着我国《消防信息化“十三五”总体规划》对消防信息化的发展规划做了统一部署&#xff0c;以城市为代表的消防通信成为专网通信行业重点关注的领域之一。目前&#xff0c;我国城市化发展面临高层建筑林立、地铁、人防工程分布密集&#xff0c;大型综合体不断涌现&a…

【运维】服务器系统安装 -- 服务器版

目录 一、环境 二、ubuntu 三、启动u盘制作 Stage 1&#xff1a;下载balena&#xff0c;制作U盘启动工具 Stage 2&#xff1a;下载Ubuntu 系统镜像&#xff08;参考上一节&#xff1a;Ubuntu 22.04.2 LTS &#xff09; Stage 3&#xff1a;将镜像写入到U盘 四、设置开启…

FUZZ工具—Boofuzz框架实际使用

接着上一篇文章FUZZ工具—Boofuzz框架来对框架进行实际的使用&#xff1b; 官方提供了很多案例模板&#xff0c;且网上关于boofuzz的使用介绍很多&#xff0c;也比较成熟&#xff0c;在各个领域都有&#xff0c;可以通过官方提供的案例也看得出来&#xff0c;然后覆盖的面也非常…

西门子变频器G120XA的快速调试方法分享

以西门子变频器G120XA为例&#xff0c;接着为大家介绍一下G120X和G120XA系列变频器的快速调试方法。 西门子发布的Sinamics G120X和G120XA系列变频器&#xff0c;专为风机和泵的应用而设计&#xff0c;实现高效节能、可靠稳定和简单易用。以G120XA为例&#xff0c;通过下面的调…