从0到1入门C++编程——05 类和对象之运算符重载、继承

news2025/1/11 2:47:27

文章目录

  • 运算符重载
    • 1.加号运算符重载
    • 2.左移运算符重载
    • 3.递增运算符重载
    • 4.赋值运算符重载
    • 5.关系运算符重载
    • 6.函数调用运算符重载
  • 继承
    • 1.继承的基本语法及继承方式
    • 2.继承中的对象模型
    • 3.继承中构造函数和析构函数的顺序
    • 4.继承中同名成员的处理方式
    • 5.继承中同名静态成员处理方式
    • 6.继承多个父类
    • 7.菱形继承

运算符重载

运算符重载是对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型。

1.加号运算符重载

加减乘除运算符的重载是一样的,只需要将operator后面的符号换成相应的运算符即可,下面以加号运算符的重载为例。
成员函数重载+运算符。

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

class Person
{
public:
	//成员函数重载+运算符
	Person operator+(Person &p)
	{
		Person temp;
		temp.a = this->a+p.a;
		temp.b = this->b+p.b;
		return temp;
	}
public:
	int a;
	int b;
};

int main()
{
	Person p1,p2;
	p1.a = 10;
	p1.b = 20;
	p2.a = 10;
	p2.b = 20;
	Person p3;
	p3 = p1 + p2;  //相当于 p3 = p1.operator+(p2);
	cout<<"p3.a="<<p3.a<<"  p3.b="<<p3.b<<endl;

	system("pause");
	return 0;
}

全局函数重载+运算符。

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

class Person
{
public:
	int a;
	int b;
};

//全局函数重载+运算符
Person operator+(Person &p1,Person &p2)
{
	Person temp;
	temp.a = p1.a+p2.a;
	temp.b = p1.b+p2.b;
	return temp;
}

int main()
{
	Person p1,p2;
	p1.a = 10;
	p1.b = 20;
	p2.a = 10;
	p2.b = 20;
	Person p3;
	p3 = p1 + p2;  //相当于 p3 = operator+(p1,p2);
	cout<<"p3.a="<<p3.a<<"  p3.b="<<p3.b<<endl;

	system("pause");
	return 0;
}

2.左移运算符重载

重载左移运算符配合友元可以实现自定义数据类型的输出。
左移运算符重载不能在成员函数中实现,因为涉及到传参,cout应在类前面。
转到cout的定义处,其是一个ostream类型的变量。

__PURE_APPDOMAIN_GLOBAL extern istream cin, *_Ptr_cin;
__PURE_APPDOMAIN_GLOBAL extern ostream cout, *_Ptr_cout;

左移运算符重载的代码如下。

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

class Person
{
	//全局函数作为友元访问私有属性
	friend ostream& operator<<(ostream &out,Person &p);
public:
	Person(int a,int b)
	{
		this->a = a;
		this->b = b;
	}
private:
	int a;
	int b;
};

//重载左移运算符
ostream& operator<<(ostream &out,Person &p)
{
	out<<"a="<<p.a<<" b="<<p.b;
	return out;
}

int main()
{
	Person p(10,20);
	cout<<p<<endl;  //直接输出对象,需要重载左移运算符才可以

	system("pause");
	return 0;
}

上面代码的运行结果如下图所示。
在这里插入图片描述

3.递增运算符重载

前置递增运算返回引用,后置递增运算返回值。
递增运算符重载的代码如下。

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

class Person
{
	friend ostream& operator<<(ostream &out,Person p);
public:
	Person()
	{
		num = 0;
	}
	//重载前置++运算符
	Person& operator++()  //需要返回引用,这样每次递增操作都是对同一个对象
	{
		num++;
		return *this;
	}
	//重载后置++运算符
	Person operator++(int)  //占位参数用来区分前置++和后置++
	{
		Person temp = *this; //先返回以前值,再++,但是返回不能在++之前,因此需要先记录
		num++;
		return temp;
	}
private:
	int num;
};

//重载左移运算符
ostream& operator<<(ostream &out,Person p)
{
	out<<p.num;
	return out;
}

int main()
{
	Person p1,p2;
	cout<<"1.p1++="<<p1++<<endl;
	cout<<"2.p1="<<p1<<endl;
	cout<<"1.++p2="<<++p2<<endl;
	cout<<"2.p2="<<p2<<endl;

	system("pause");
	return 0;
}

上面代码的运行结果如下图所示。
在这里插入图片描述

4.赋值运算符重载

赋值运算符重载是为了实现涉及堆区内存的拷贝,要以深拷贝的形式实现,浅拷贝的方式在析构函数执行时会发生错误。
赋值运算符重载的代码如下。

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

class Person
{
public:
	Person(int age)
	{
		this->age = new int(age);
	}
	
	//重载赋值运算符
	Person& operator=(Person &p)
	{
		//age = p.age;   //默认的重载内容,浅拷贝
		//先判断属性是否在堆区,如果在就先释放,再接收拷贝
		if(age != NULL)
		{
			delete age;
			age = NULL;
		}
		age = new int(*p.age);  //深拷贝实现
		return *this;   //为了实现连等赋值,需要返回自身而不能是void类型
	}

	//析构函数中释放堆区内存
	~Person()
	{
		if(age != NULL)
		{
			delete age;
			age = NULL;
		}
	}

	int *age;
};

void fun()   //需要在函数中测试,这样函数返回后就会调用析构函数
{
	Person p1(18);
	Person p2(20);
	Person p3(22);
	p3 = p2 = p1;
	cout<<"p1的年龄为:"<<*p1.age<<endl;
	cout<<"p2的年龄为:"<<*p2.age<<endl;
	cout<<"p3的年龄为:"<<*p3.age<<endl;
}

int main()
{
	fun();

	system("pause");
	return 0;
}

上面代码的运行结果如下图所示。
在这里插入图片描述

5.关系运算符重载

重载两个关系运算符,可以让两个自定义类型的对象进行对比。
关系运算符重载的代码如下。

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

class Person
{
public:
	Person(string name,int age)
	{
		this->name = name;
		this->age = age;
	}
	
	//重载关系运算符
	bool operator==(Person &p)
	{
		if(name == p.name && age == p.age)
			return true;
		else
			return false;
	}

private:
	string name;
	int age;
};

void fun()   //需要在函数中测试,这样函数返回后就会调用析构函数
{
	Person p1("aaa",18);
	Person p2("bbb",20);
	Person p3("aaa",18);
	if(p1==p2)
		cout<<"p1和p2年龄和名字都相同!"<<endl;
	else
		cout<<"p1和p2不相同!"<<endl;
	if(p1==p3)
		cout<<"p1和p3年龄和名字都相同!"<<endl;
	else
		cout<<"p1和p3不相同!"<<endl;
}

int main()
{
	fun();

	system("pause");
	return 0;
}

上面代码的运行结果如下图所示。
在这里插入图片描述

6.函数调用运算符重载

函数调用运算符是 () ,由于重载后使用的方式像函数调用,因此称为仿函数,仿函数没有固定写法,非常灵活。
函数调用运算符重载的代码如下。

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

class Person
{
public:
	//重载函数调用运算符
	void operator()(string s)
	{
		cout<<s<<endl;
	}
	void operator()(int a,int b)
	{
		cout<<"result = "<<a+b<<endl;
	}
};

void fun(string s) 
{
	cout<<s<<endl;
}

int main()
{
	Person p;
	p("Hello operator()!");  //重载函数调用运算符后调用
	fun("Hello fun()!");  //函数调用
	p(100,200); 
	Person()(10,20);   //匿名对象调用

	system("pause");
	return 0;
}

上面代码的运行结果如下图所示。
在这里插入图片描述


继承

1.继承的基本语法及继承方式

继承是面向对象的三大特性之一。
类与类之间存在特殊的关系,比如下面的类中,下级的成员除了拥有上一级的共性外,还有自己的特性。
在这里插入图片描述
这个时候可以使用继承,减少重复的代码,这也是通过继承带来的好处。
继承的语法:class 子类名 :继承方式(public等) 父类名
继承方式包括公共继承(public) 、保护继承(protected) 和私有继承(private) 。
父类也称基类,子类也称派生类。
派生类中的成员包含两部分,一部分是从基类继承过来的,一类是自己增加的成员,从基类继承过来的表现为共性,子类中新增的成员体现了其个性。
通过公共继承(public) 方式,成员属性或方法在父类中是什么样的访问方式,在子类中还是怎样的访问方式;通过保护继承(protected) 方式,成员属性或方法在父类中是公共或保护访问方式的,在子类中以保护方式访问;通过私有继承(private)方式,成员属性或方法在父类中是公共或保护访问方式的,在子类中以私有方式访问;父类中私有的成员属性或方法在子类中不能被访问。保护权限下的成员属性或方法在子类内可以访问,子类外不可以访问。
在这里插入图片描述
如果再对子类做继承,同样要看继承方式,子类中私有的属性或方法经继承后全都访问不了。
值得一提的是,父类中的私有成员只是被隐藏了,但是仍然会继承下去。
网页中一般都是这样设计的,有公共的头部和底部信息,点开不同的链接之后,这些公有的信息没有变化,但是却有自己独有的部分,这就用到了继承。
如果不使用继承,对上面提到的网页例子以普通的方式来实现,代码如下所示。

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

class Java
{
public:
	void head()
	{
		cout<<"公共头部信息..."<<endl;
	}
	void foot()
	{
		cout<<"公共底部信息..."<<endl;
	}
	void content()
	{
		cout<<"Java学习视频..."<<endl;
	}
};

class Python
{
public:
	void head()
	{
		cout<<"公共头部信息..."<<endl;
	}
	void foot()
	{
		cout<<"公共底部信息..."<<endl;
	}
	void content()
	{
		cout<<"Python学习视频..."<<endl;
	}
};

class CPP
{
public:
	void head()
	{
		cout<<"公共头部信息..."<<endl;
	}
	void foot()
	{
		cout<<"公共底部信息..."<<endl;
	}
	void content()
	{
		cout<<"C++学习视频..."<<endl;
	}
};

void fun() 
{
	Java ja;
	ja.head();
	ja.content();
	ja.foot();
	cout<<"----------------"<<endl;
	Python py;
	py.head();
	py.content();
	py.foot();
	cout<<"----------------"<<endl;
	CPP c;
	c.head();
	c.content();
	c.foot();
}

int main()
{
	fun();

	system("pause");
	return 0;
}

可以看到,不同的类中用到了许多重复的代码,如果采用继承的方式,优化后的代码如下。

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

class BasePage
{
public:
	void head()
	{
		cout<<"公共头部信息..."<<endl;
	}
	void foot()
	{
		cout<<"公共底部信息..."<<endl;
	}
};

//继承基类,一定要加继承方式public,不写默认是private,无法访问
class Java : public BasePage
{
public:
	void content()
	{
		cout<<"Java学习视频..."<<endl;
	}
};

class Python : public BasePage
{
public:
	void content()
	{
		cout<<"Python学习视频..."<<endl;
	}
};

class CPP : public BasePage
{
public:
	void content()
	{
		cout<<"C++学习视频..."<<endl;
	}
};

void fun() 
{
	Java ja;
	ja.head();
	ja.content();
	ja.foot();
	cout<<"----------------"<<endl;
	Python py;
	py.head();
	py.content();
	py.foot();
	cout<<"----------------"<<endl;
	CPP c;
	c.head();
	c.content();
	c.foot();
}

int main()
{
	fun();

	system("pause");
	return 0;
}

上面的两个代码运行结果是一样的,如下图所示,但是通过继承方式写出来的代码减少了很多的重复,这种重复在多继承的情况的尤为明显。
在这里插入图片描述

2.继承中的对象模型

父类中所有的非静态成员属性都会被子类继承下去,父类中的私有成员属性被编译器隐藏了,但是仍然会被继承。
下面代码很好的说明了父类中的哪些属性被子类继承了。
在这里插入图片描述

3.继承中构造函数和析构函数的顺序

先执行父类的构造函数,再执行子类的构造函数;析构函数的执行顺序是先执行子类的析构函数,再执行父类的析构函数。
测试构造函数和析构函数的顺序的代码如下。

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

class Parent
{
public:
	Parent()
	{
		cout<<"Parent构造函数!"<<endl;
	}
	~Parent()
	{
		cout<<"Parent析构函数!"<<endl;
	}
};

class Son : public Parent
{
public:
	Son()
	{
		cout<<"Son构造函数!"<<endl;
	}
	~Son()
	{
		cout<<"Son析构函数!"<<endl;
	}
};

void fun()
{
	Son s;
}

int main()
{
	fun();

	system("pause");
	return 0;
}

上面代码的执行结果如下图所示。
在这里插入图片描述

4.继承中同名成员的处理方式

如果子类有和父类同名的成员,访问子类成员的时候,直接访问即可,访问父类成员则要加父类名限定作用域。
如果子类有和父类同名的成员函数,子类的同名成员会隐藏掉父类中的所有同名成员函数,包括重载的函数。如果要访问到父类中被隐藏的同名成员函数,需要加作用域。
继承中同名成员属性或成员方法的使用和调用如下图所示。

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

class Parent
{
public:
	Parent()
	{
		a = 10;
	}
	void fun()
	{
		cout<<"Parent类中的fun()函数调用!"<<endl;
	}
	void fun(int b)
	{
		cout<<"Parent类中的fun(int b)函数调用!"<<endl;
	}
	int a;
};

class Son : public Parent
{
public:
	Son()
	{
		a = 20;
	}
	void fun()
	{
		cout<<"Son类中的fun()函数调用!"<<endl;
	}
	int a;
};

void fun()
{
	Son s;
	cout<<"s.a = "<<s.a<<endl;
	cout<<"s.Parent::a = "<<s.Parent::a<<endl;
	s.fun();
	s.Parent::fun();
	s.Parent::fun(1);
}

int main()
{
	fun();

	system("pause");
	return 0;
}

上面代码的执行结果如下图所示。
在这里插入图片描述

5.继承中同名静态成员处理方式

同名静态成员的处理方式和非静态处理方式一样,不过静态成员的访问方式既可以通过对象实现,也可以通过类名实现。
通过类名访问实现时需要注意两个::的区别,前一个::是以类名的方式访问成员,后一个::则是区分同名成员的作用域。
继承中同名静态成员处理方式的代码如下。

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

class Parent
{
public:
	static void fun()
	{
		cout<<"Parent类中的fun()函数调用!"<<endl;
	}
	static void fun(int b)
	{
		cout<<"Parent类中的fun(int b)函数调用!"<<endl;
	}
	static int a;  //类内声明
};

class Son : public Parent
{
public:
	static void fun()
	{
		cout<<"Son类中的fun()函数调用!"<<endl;
	}
	static int a;
};

int Parent::a = 10;   //类外初始化
int Son::a = 20; 

void fun()
{
	Son s;
	cout<<"通过实例化的对象访问静态成员:"<<endl;
	cout<<"s.a = "<<s.a<<endl;
	cout<<"s.Parent::a = "<<s.Parent::a<<endl;
	s.fun();
	s.Parent::fun();
	s.Parent::fun(1);
	cout<<"通过类访问静态成员:"<<endl;
	cout<<"Son::a = "<<Son::a<<endl;
	//cout<<"Parent::a = "<<Parent::a<<endl;    //通过父类直接访问的,不是以子类访问的
	cout<<"Parent::a = "<<Son::Parent::a<<endl;  
	//第一个::是以类名的方式访问静态成员;第二个::是以限定同名成员变量的作用域
	Son::fun();
	Son::Parent::fun();
	Son::Parent::fun(1);
}

int main()
{
	fun();

	system("pause");
	return 0;
}

上面代码的执行结果如下图所示。
在这里插入图片描述

6.继承多个父类

C++中允许一个类继承多个类,多继承可能会出现同名成员,需要加作用域进行区分。
多继承语法:class 子类名 :继承方式 父类名1,继承方式 父类名2,…
多继承的代码示例如下所示。

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

class Base1
{
public:
	Base1()
	{
		a = 10;
	}
	int a;
};

class Base2
{
public:
	Base2()
	{
		a = 20;
	}
	int a;
};

class Son : public Base1, public Base2
{
public:
	Son()
	{
		a = 30;
	}
	int a;
};

void fun()
{
	Son s;
	cout<<"s.a = "<<s.a<<endl;
	cout<<"s.Base1::a = "<<s.Base1::a<<endl;
	cout<<"s.Base2::a = "<<s.Base2::a<<endl;
}

int main()
{
	fun();

	system("pause");
	return 0;
}

上面代码的执行结果如下图所示。
在这里插入图片描述
如果不加作用域,默认访问的是本类的成员变量,如果要访问不同类中的同名成员变量,需要加上作用域才能实现访问。

7.菱形继承

菱形继承:两个子类(派生类)继承了同一个父类(基类),同时又有某个类继承了两个子类,菱形继承也称钻石继承。
在这里插入图片描述
菱形继承的一个典型例子如下图所示。
在这里插入图片描述
菱形继承中,子类继承父类的时候会将属性在各自的类中继承一份,因此,再有类继承子类就会得到两个相同的属性,所以菱形继承中一定存在着同名成员,导致资源浪费且有出现歧义。要利用虚继承解决同名成员的问题,在继承方式前面加上关键字virtual就代表虚继承。
虚继承继承的不再是成员的属性,而是一个虚基类指针,这两个指针在子类中通过不同的偏移量最终指向父类中的成员属性,如下图所示。
在这里插入图片描述
菱形继承的代码示例如下。

#include <iostream>
#include <string>
using namespace std;
//基类
class Animal
{
public:
	int age;
};
//派生类
class Sheep : virtual public Animal{};
class Tuo : virtual public Animal{};
//继承两个派生类
class SheepTuo : public Sheep, public Tuo{};

void fun()
{
	SheepTuo st;
	st.age = 18;
	cout<<"st.age = "<<st.age<<endl;
	cout<<"st.Sheep::age = "<<st.Sheep::age<<endl;
	cout<<"st.Tuo::age = "<<st.Tuo::age<<endl;
	cout<<"st.Animal::age = "<<st.Tuo::age<<endl;
	cout<<"sizeof(st) = "<<sizeof(st)<<endl;
}

int main()
{
	fun();

	system("pause");
	return 0;
}

上面代码的执行结果如下图所示。
在这里插入图片描述
可以看到,通过虚继承,访问成员属性的时候直接通过.访问即可, 不用再加类名作为作用域,因为继承下来的数据只有一份,不会产生歧义。
最终类的大小是12个字节,其中有4个字节是继承自父类的成员属性,另外8个字节分别是来自两个派生类的虚基类指针。
若不采用虚继承的方式,上面类的大小是8个字节,父类中的成员属性被两个派生类继承了,再由一个类继承了两个派生类的属性,因此就是8字节大小。
在这里插入图片描述


本文参考视频:
黑马程序员匠心之作|C++教程从0到1入门编程,学习编程不再难

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

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

相关文章

18张AI电脑动漫超清壁纸免费分享

18张AI电脑动漫壁纸&#xff0c;紫色系和暗黑系&#xff0c;都很不错&#xff0c;喜欢的朋友可以拿去 CSDN免积分下载

【动态规划】C++ 算法458:可怜的小猪

作者推荐 视频算法专题 涉及知识点 动态规划 数学 力扣458:可怜的小猪 有 buckets 桶液体&#xff0c;其中 正好有一桶 含有毒药&#xff0c;其余装的都是水。它们从外观看起来都一样。为了弄清楚哪只水桶含有毒药&#xff0c;你可以喂一些猪喝&#xff0c;通过观察猪是否…

SD-WAN对企业网络升级的价值

在当今数字化飞速发展的时代&#xff0c;企业对网络的依赖越来越深&#xff0c;如何在确保IT正常运行的同时降低成本成为企业CIO和业务经理共同关注的焦点。SD-WAN的出现为企业组网带来了崭新的可能性&#xff0c;成为降低开支、提高效率和改善用户体验的重要工具。 企业在数字…

QT上位机开发(属性页面的设计)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 窗口设计的时候&#xff0c;如果很多内容一个page放不下&#xff0c;那么这个时候我们一般都会选择使用tab来进行处理。安装了tab之后&#xff0c;…

NR中如何判断是否需要measurement gap来做邻区的测量?

先看下NR中定义的测量。 intra-freq 测量和inter-freq测量可以分为以下几类&#xff1a; 1 SSB based intra-freq 测量&#xff1a;serving cell SSB的center freq与邻区 SSB的center freq 相同并且两个SSB 的SCS也相同。 2 SSB based inter-freq 测量&#xff1a;serving ce…

使用AI平台处理训练和微调数据

Llama.cpp是Georgi Gerganov 基于 Meta 的 LLaMA 模型 手写的纯 C/C 版本&#xff0c;让我们实现了在笔记本电脑上部署和体验AI大模型&#xff0c;实现没有GPU也可以运行AI大模型。执行起来虽然比较慢&#xff0c;但是只能算做体验&#xff0c;还可以选择不同语言。某个模型使用…

自动化的运维管理:探究Kubernetes工作机制的奥秘

1 云计算时代的操作系统 Kubernetes 是一个生产级别的 容器编排平台 和 集群管理系统 &#xff0c;能够 创建、调度容器&#xff0c;监控、管理服务器。 容器是什么&#xff1f;容器是软件&#xff0c;是应用&#xff0c;是进程。服务器是什么&#xff1f;服务器是硬件&#…

通过 Elastic Stack 充分利用电信领域生成式 AI 的力量

作者&#xff1a;Elastic Piotr Kobziakowski, Jrgen Obermann 在瞬息万变的电信领域&#xff0c;Elastic Stack 与生成式 AI 的集成正在开创运营效率和创新的新时代。 这些技术不仅增强了网络运营&#xff0c;而且还彻底改变了各个部门的内部流程。 下面&#xff0c;我们将深入…

OpenAI推出GPT商店和ChatGPT Team服务

&#x1f989; AI新闻 &#x1f680; OpenAI推出GPT商店和ChatGPT Team服务 摘要&#xff1a;OpenAI正式推出了其GPT商店和ChatGPT Team服务。用户已经创建了超过300万个ChatGPT自定义版本&#xff0c;并分享给其他人使用。GPT商店集结了用户为各种任务创建的定制化ChatGPT&a…

联手英特尔,释放星飞分布式全闪存储潜能

近日&#xff0c;英特尔官网发布了与 XSKY 星辰天合联手打造的解决方案&#xff0c;即 XSKY 的新一代全闪分布式存储系统 XINFINI&#xff0c;该存储系统采用英特尔 QAT 加速数据压缩/解压缩&#xff0c;从而大幅度提升存储系统性能。 全闪存储系统面临的解压缩挑战 在存储系统…

LeetCode刷题--- 地下城游戏

个人主页&#xff1a;元清加油_【C】,【C语言】,【数据结构与算法】-CSDN博客 个人专栏 力扣递归算法题 http://t.csdnimg.cn/yUl2I 【C】 ​​​​​​http://t.csdnimg.cn/6AbpV 数据结构与算法 ​​​http://t.csdnimg.cn/hKh2l 前言&#xff1a;这个专栏主要讲述动…

【C++】零碎知识点汇总_1

abs() 函数&#xff1a; abs() 是 C 和 C 标准库中的函数&#xff0c;用于计算整数的绝对值。在 C 中&#xff0c;abs() 函数的原型位于 <stdlib.h> 头文件中&#xff0c;用于整数类型在 C 中&#xff0c;abs() 函数的原型位于 <cstdlib> 头文件中&#xff0c;并可…

【漏洞复现】Hikvision SPON IP网络对讲广播系统存在命令执行漏洞CVE-2023-6895

漏洞描述 Hikvision Intercom Broadcasting System是中国海康威视(Hikvision)公司的一个对讲广播系统。 Hikvision Intercom Broadcasting System是中国海康威视(Hikvision)公司的一个对讲广播系统。Hikvision Intercom Broadcasting System 3.0.3_20201113_RELEASE(HIK)版…

SpringBoot集成Skywalking实现分布式链路追踪

官方网址&#xff1a; Apache SkyWalking官方文档&#xff1a; SkyWalking 极简入门 | Apache SkyWalking下载地址&#xff1a;Downloads | Apache SkyWalking Agent&#xff1a;以探针的方式进行请求链路的数据采集&#xff0c;并向管理服务上报&#xff1b; OAP-Service&am…

2023年快要结束了,今年哪些计算机书值得推荐?

2023年推荐新书有如下几本&#xff1a; 1、软件开发安全之道概念、设计与实施 软件安全设计和实施&#xff0c;覆盖安全概念、设计与实践&#xff0c;让您轻松应对各种威胁与挑战&#xff0c;帮助读者培养安全意识&#xff0c;全面了解软件开发安全之道。 2、C Templates&…

云服务器搭建GitLab

经验总结&#xff1a; 1、配置需求&#xff1a;云服务器内存最低4G 2、内存4G的云服务器&#xff0c;在运行容器后&#xff0c;会遇到云服务器操作卡顿问题&#xff0c;这里有解决方案 转载&#xff1a;服务器搭建Gitlab卡顿解决办法-CSDN博客 3、云服务器的操作系统会影响…

OpenAI大反击!称纽约时报涉嫌故意操纵,且数据是「合理使用」

大家好我是二狗。 《纽约时报》向法院起诉OpenAI侵犯版权后续事件来了&#xff01; 就在今天&#xff0c;OpenAI进行了一场“危机公关”&#xff1a;直接在官方博客上撰文发声&#xff0c;反驳《纽约时报》的诉讼&#xff0c;其主要观点有四个&#xff1a; 1、我们正在和新闻…

将WebGL打包的unity项目部署至Vue中

一、webgl打包 创建一个空项目&#xff08;或者直接使用现成的项目都可以&#xff09;这里以该空项目为例子 注意&#xff1a; 如果你的unity项目中有文字&#xff0c;不需要使用unity默认的字体&#xff0c;需要更改它的字体&#xff0c;否则在最后生成的页面中会显示不出来…

Vue过滤器详解

聚沙成塔每天进步一点点 本文内容 ⭐ 专栏简介基本用法多个过滤器的串联过滤器在指令中的应用全局过滤器 ⭐ 本期推荐 ⭐ 专栏简介 Vue学习之旅的奇妙世界 欢迎大家来到 Vue 技能树参考资料专栏&#xff01;创建这个专栏的初衷是为了帮助大家更好地应对 Vue.js 技能树的学习。每…

reactNative0.71版本的使用

开发环境配置 参考reactNative 官网 版本选中0.71 打包配置 1. IOS 打开项目 -> 进入ios目录->执行命令 pod install ->项目名称.xcworkspace -> 使用xcode打开->配置证书 证书配置截图如下 &#x1f4a1;tips&#xff1a;TARGETS目录下会有多个文件&#x…